Algorithm-Pattern
  • Introduction
  • C & C++
    • C语言
      • C/C++编译器
      • 宏的使用
      • 编译过程
      • 指针 & 数组
      • 柔性数组
      • 函数指针 & 回调函数
      • C标准库之stdio
      • C标准库之string
      • C标准库之errno
      • C标准库之stdarg
      • C标准库之regex
    • C++基础语法
      • 自增(++) & 自减(--)
      • c语言到c++
      • 可变模板参数
      • 强制类型转换
      • C/C++类型转换的本质
      • 指针 & 引用
      • const的用法
      • static的用法
      • 重要的关键字(一)
      • 重要的关键字(二)
      • 内存申请和释放
      • 内联函数
      • 函数 & 运算符重载
      • 面向对象之封装
      • 构造函数 & 析构函数
      • 面向对象之继承
      • 面向对象之多态
      • 泛型编程
      • 异常
      • 再谈函数指针
    • C++并发编程
      • C++的锁
      • 并发与多线程
    • C++高级特性
      • 函数对象
      • 移动语义 & 完美转发
      • lambda表达式
      • RTTI技术
      • RAII技术
      • 智能指针
      • 模板的特化
      • C++静态库和动态库
      • 内存溢出和内存泄漏
    • STL基础
      • String
      • array/vector/list
      • deque/priority_queue
      • set/map
      • unordered_set/unordered_map
      • algorithm_1
      • functional
      • allocator
    • C++标准库
      • IO
      • Tuple
      • regex
      • bitset
      • numeric
    • STL深入源码
      • vector内部实现
      • deque内部实现
      • sort函数实现
    • 第三方库
      • JsonCpp
      • ProtoBuf
  • 数据结构
    • 线性表
    • 字符串
    • 栈和队列
    • 二叉树
    • 平衡二叉树
    • 平衡多路搜索树
    • 树结构的延申
    • 图
    • 二进制
    • 散列表
  • 算法基础
    • 排序算法
    • 查找算法
    • 数学问题
    • 并查集
    • 递归算法
    • 附加——主定理
    • Catalan数
  • 算法设计思想
    • 滑动窗口思想
    • BFS/DFS
    • 二分法
    • 回溯法
    • 贪心算法
    • 分治法
    • 动态规划
    • 分支限界算法
    • 有限状态机(FSM)
  • LeetCode系列
    • 死磕二叉树
    • 股票买卖问题
    • 打家劫舍问题
    • 跳跃游戏问题
    • 括号匹配问题
    • 石子游戏问题
    • 子序列问题
    • 数组 & 矩阵
    • 排列 & 组合
  • 经典算法问题
    • 几何问题
    • 区间问题
    • 背包问题
    • 石子堆问题
    • 表达式求值
  • 面试题
    • 数据结构和算法基础
    • 程序设计题
      • 实现双线程交替打印
      • C++实现读写锁
      • 实现阻塞队列
      • 实现环形队列
      • 实现线程池
      • 实现智能指针
      • 实现string类
      • 实现高性能local cache
      • 实现内存池
      • 生产者-消费者模型
      • 设计定时器
    • 经典的算法题
    • C++面试题总结
    • 面试算法题总结
由 GitBook 提供支持
在本页

这有帮助吗?

  1. 面试题
  2. 程序设计题

实现智能指针

智能指针的一种通用实现方法是采用引用计数,将一个计数器与类指向的对象相关联,引用计数跟踪共有多少个类对象共享同一指针。

  1. 每次创建类的新对象时,初始化指针并将引用计数置为1;

  2. 当对象作为另一对象的副本而创建时,拷贝构造函数拷贝指针并增加与之相应的引用计数;

  3. 对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数减至0,则删除对象),并增加右操作数所指对象的引用计数,这是因为左侧的指针指向了右侧指针所指向的对象,因此右指针所指向的对象的引用计数+1;

  4. 调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)。

  5. 智能指针就是模拟指针动作的类,因此会重载 -> 和 * 操作符。

template<typename T>
class SharedPointer {
public:
    SharedPointer(T *ptr = nullptr) : _ptr(ptr){
        if(ptr != nullptr)
            _count = new int(1);
        else
            _count = new int(0);
    }
    // 拷贝构造函数
    SharedPointer(const SharedPointer& ptr){
        if(this != &ptr){
            this->_ptr = ptr._ptr;
            this->_count = ptr._count;
            (*this->_count) ++;
        }
    }
    // 拷贝赋值运算符
    SharedPointer& operator = (const SharedPointer &ptr){
        if(this->_ptr == ptr._ptr){
            return *this;
        }

        if(this->_ptr){
            (*this->_count) --;
            if((*this->_count) == 0){
                delete this->_count;
                delete this->_ptr;
            }
        }

        this->_ptr = ptr._ptr;
        this->_count = ptr._count;
        (*this->_count) ++;
        return *this;
    }

    ~SharedPointer(){
        (*this->_count) --;
        if((*this->_count) == 0){
            delete this->_count;
            delete this->_ptr;
        }
    }

public:
    T& operator*(){
        return *(this->_ptr);
    }

    T* operator->(){
        return this->_ptr;
    }

    int use_count(){
        return *(this->_count);
    }

    T* get(){
        return this->_ptr;
    }
    // 重载布尔值操作
    operator bool(){
        return this->_ptr == nullptr;
    }

private:
    T *_ptr;
    int *_count;
};

// 测试代码
void testSharedPointer(){
    SharedPointer<int> p1(new int(10));
    cout << "值:" << *(p1.get()) << " 引用计数:" << p1.use_count() << endl;
    *p1 = 100;
    cout << "值:" << *p1 << " 引用计数:" << p1.use_count() << endl;

    {
        SharedPointer<int> p2(p1);
        *p2 = 3;
        cout << "值:" << *p2 << " 引用计数:" << p1.use_count() << endl;

        SharedPointer<int> p3 = p2;
        *p3 = 55;
        cout << "值:" << *p3 << " 引用计数:" << p1.use_count() << endl;

        cout << "值:" << *p2 << " 引用计数:" << p1.use_count() << endl;
    }

    cout << "值:" << *p1 << " 引用计数:" << p1.use_count() << endl;

    if(p1){
        cout << "True" << endl;
    }

    SharedPointer<string> q1(new string("我是string1"));
    cout << "值:" << (*(q1)).c_str() << " size:" << q1->size() << endl;
}

实现智能指针还有两种经典的策略:一是引入辅助类,二是使用句柄类。后序会讨论。

上一页实现线程池下一页实现string类

最后更新于4年前

这有帮助吗?