【C++基础】手撕shared_ptr

总体思路

  1. 使用类模板来实现多类型支持

  2. 构造函数(动态创建)、析构函数(销毁对象)

  3. 拷贝构造函数

  4. 拷贝运算符(->、*)

  5. 实现移动构造和移动运算符

  6. 对于引用计数的操作服从智能指针的设计规则

整体框架

tmplate<class T>
class new_shared_ptr {
pubilc:
    new_shared_ptr();
 
    new_shared_ptr(const new_shared_ptr& p);                 //构造
 
    ~new_shared_ptr();                                       //析构
 
    new_shared_ptr& operator=(const new_shared_ptr<T>& obj);  //拷贝运算符

    new_shared_ptr(new_shared_ptr&& dying_obj);             // 移动构造

    new_shared_ptr& operator=(new_shared_ptr&& dying_obj);  //移动赋值运算符
    
    int operator->();        //->运算符
    
    int operator*();         //* 运算符
 
private:
    T* ptr;
    int* ref_count;
    mutex *m_pMutex;
}

构造函数

new_shared_ptr(): ptr(new T), ref_count(new int(1)), mutex(new mutex) {}

拷贝构造函数

new_shared_ptr(const new_shared_ptr& p) {
    //先对当前对象进行初始化
    ptr = p.ptr;
    ref_count = p.ref_count;
    mutex = p.mutex;
    //判断拷贝进来的指针是否指向空,不指向空表明当前地址多了一个指向,引用计数加一
    if (p != nullptr) {
        m_pMutex->lock();
        (*ref_count)++;
        m_pMutex->unlock();
    }
}

 重载=、->、* 运算符

new_shared_ptr& operator=(const new_shared_ptr<T>& obj) {
    //检查自赋值
    if (obj.ptr == ptr) return *this;
    //防止空指针指向别处
    if (ptr) {
        //自身指向即将改变,判断原先指向的地址是否销毁
        m_pMutex->lock();
        (*ref_count)--;
        m_pMutex->unlock();
        if (ref_count == 0) {
            delete ptr;
            delete ref_count;
            delete m_pMutex;
        }
        ptr = obj.ptr;
        ref_count = obj.ref_count;
        m_pMutex = obj.m_pMutex;
        m_pMutex->lock();
        (*ref_count)++;
        m_pMutex->unlock();
    }
    return *this;
}
 
T* operator->() return ptr;
T& operator*() return *ptr;

移动构造

当使用移动构造函数创建一个新的智能指针并将另一个智能指针的资源所有权转移给它时,移动构造不会影响引用计数。引用计数会在资源所有权转移后保持不变,原来的智能指针会被置为  nullptr ,不再指向资源。这确保资源的唯一所有权。

new_shared_ptr(new_shared_ptr&& dying_obj)
      : ptr(nullptr), ref_count(nullptr) {
  // 初始化后,调用swap,交换指针和引用计数,相当于清除了原有的shared_ptr,把它们都置为nullptr了
    dying_obj.swap(*this);
  }

  void swap(new_shared_ptr& other) {
    std::swap(ptr, other.ptr);
    std::swap(ref_count, other.ref_count);
  }

移动赋值

当使用移动赋值运算符将一个智能指针的资源所有权转移给另一个智能指针时,移动赋值不会影响引用计数。与移动构造类似,资源的所有权转移后,原来的智能指针会被置为 nullptr ,引用计数保持不变。

new_shared_ptr& operator=(new_shared_ptr&& dying_obj) {
    /* 创建一个临时变量,将待移动的智能指针转移到临时变量 */
    new_shared_ptr(std::move(dying_obj)).swap(*this);
    return *this;
  }

析构函数

~new_shared_ptr() {
    if (!ptr || (*ref_count == 1)) {
        delete ptr;
        delete m_pMutex;
        delete ref_count;
    } else {
        m_pMutex->lock();
        (*ref_count)--;
        m_pMutex->unlock();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
shared_ptrC++11 中引入的智能指针类型,可用于管理动态分配的对象。它是通过引用计数的方式来跟踪对象的使用情况,并在不再需要时自动释放相关的内存。 shared_ptr 的过程大致如下: 1. 定义 shared_ptr 类:首先,你需要定义一个类模板 shared_ptr,它包含两个主要成员:指向动态分配内存的原始指针和一个指向引用计数的指针。此外,你还需要实现构造函数、析构函数、拷贝构造函数和赋值运算符等成员函数。 2. 初始化:在 shared_ptr 的构造函数中,你需要将原始指针和引用计数初始化为空,并将引用计数置为 1。 3. 拷贝构造函数和赋值运算符:在拷贝构造函数和赋值运算符中,你需要更新原始指针和引用计数。当一个 shared_ptr 被拷贝时,引用计数应该递增;当一个 shared_ptr 被赋值给另一个 shared_ptr 时,应该先递减左操作数的引用计数,然后再递增右操作数的引用计数。 4. 引用计数管理:你需要实现对引用计数的正确管理。当引用计数变为零时,表示没有任何 shared_ptr 指向该对象,此时应该释放相关的内存。 5. 解引用操作符和箭头操作符重载:为了使 shared_ptr 使用起来像原始指针一样,你需要重载解引用操作符和箭头操作符,以便可以直接访问对象或对象的成员。 6. 其他辅助函数:你可以实现其他辅助函数,如 get() 函数用于获取原始指针,reset() 函数用于重置 shared_ptr,以及 operator bool() 函数用于检查 shared_ptr 是否为空等。 需要注意的是,动实现 shared_ptr 需要处理好线程安全性和异常安全性等问题,这需要一定的经验和技巧。因此,在实际项目中,建议使用标准库提供的 shared_ptr 类型,以便确保代码的可靠性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值