实现一个简单的shared_ptr

本文深入探讨了C++中的智能指针概念,重点讲解了auto_ptr和shared_ptr的工作原理及应用场景。通过自定义实现shared_ptr,展示了引用计数机制如何帮助管理内存资源,避免内存泄漏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在看《effective C++》第3章时,基本上都是auto_ptr和shared_ptr的原理与应用。
auto_ptr和shared_ptr基本原理都是将构造好(new)的裸资源指针交给对象去打理,当对象释放时自动调用析构函数,在析构函数中delete裸资源指针;从而避免遗忘手动释放指针。
auto_ptr通过拷贝构造或者通过=赋值后,原来的auto_ptr就失效了(裸资源指针赋值为0),裸资源指针的所有权转移到新的auto_ptr对象中去了。
更多关于auto_ptr,参考我之前的总结“ C++智能指针auto_ptr”。
在C++11中,auto_ptr已经被unique_ptr取代,关于unique_ptr,参考下“ unique_ptr使用简介”。
shared_ptr通过引用计数(reference-counting smart pointer,RCSP),可以让多个智能指针对象同时拥有裸资源指针,只有在最后一个shared_ptr对象释放时,才会delete裸资源指针。

我在下面的代码中实现了一个简单的shared_ptr,后续看到模板部分再来补充吧。

#include<iostream>  
#include<cassert>
using namespace std;  
   
template <class T>  
class shared_ptr  
{  
private:  
    T *_ptr;  
    int *pCount;  //计数指针;
    //int pCount; //如果用对象,每次初始化之后都是新的值;如果用static,则不同的智能指针会拥有相同的count。

public:  
    shared_ptr(T *p) : _ptr(p), pCount(new int(1))  //构造函数  
    {  
    }
    shared_ptr(shared_ptr& another)
    {
      _ptr = another._ptr;
	   
      pCount = another.pCount;  //浅拷贝,所有对象指向公有的 *pCount
      ++(*pCount);
    }
    T& operator *()        //重载*操作符  
    {  
        return *_ptr;  
    }  
    T* operator ->()       //重载->操作符  
    {  
        return _ptr;  
    }
    int getCount()  //获取引用计数
    {
        return *pCount;
    }	
    ~shared_ptr()  //析构函数  
    {   
       (*pCount)--;
       if(0 == *pCount)
       {
           delete _ptr;
           delete pCount;
       }        		
    }  
};  
  
class Test
{
public:
  Test()
  {
    cout<<"constructor of Test()"<<endl;
  }
  ~Test()
  {
    cout<<"de-constructor of Test()"<<endl;
  }
  void helloTest()
  {
    cout<<"helloTest()"<<endl;  
  }
  int v;
};  

//入参和出参,分别会调用SmartPointer的拷贝构造函数和析构函数
//引用计数pCount也会分别+1和-1.  
void testSmartPointer(shared_ptr<Test> sp) 
{
   cout<<sp.getCount()<<endl;
}  
  
int main(void)  
{  
    //构造一次,拷贝三次
    Test *p = new Test;
    shared_ptr<Test> s_p(p);
    //shared_ptr<Test> s_p1(p);    //错误,p会被多析构一次
    shared_ptr<Test> s_p2(s_p);
    shared_ptr<Test> s_p3(s_p2);
    shared_ptr<Test> s_p4(s_p3);
    s_p->helloTest();
    (*s_p4).helloTest();
	
    testSmartPointer(s_p4);
		
    s_p->v = 10;
    assert(s_p4->v == 10);

    cout<<s_p4.getCount()<<endl;	
    assert(s_p.getCount() == s_p4.getCount());	
    return 0;  
}  


以下是一个简单shared_ptr实现,仅用于参考。 ```c++ template<typename T> class shared_ptr { public: shared_ptr() : ptr(nullptr), ref_count(nullptr) {} shared_ptr(T* p) : ptr(p), ref_count(new int(1)) {} shared_ptr(const shared_ptr<T>& other) : ptr(other.ptr), ref_count(other.ref_count) { if (ref_count) ++(*ref_count); } ~shared_ptr() { dispose(); } shared_ptr<T>& operator=(const shared_ptr<T>& other) { if (this != &other) { dispose(); ptr = other.ptr; ref_count = other.ref_count; if (ref_count) ++(*ref_count); } return *this; } T* operator->() const { return ptr; } T& operator*() const { return *ptr; } bool operator==(const shared_ptr<T>& other) const { return ptr == other.ptr; } bool operator!=(const shared_ptr<T>& other) const { return !(*this == other); } bool operator<(const shared_ptr<T>& other) const { return ptr < other.ptr; } bool operator>(const shared_ptr<T>& other) const { return other < *this; } bool operator<=(const shared_ptr<T>& other) const { return !(other < *this); } bool operator>=(const shared_ptr<T>& other) const { return !(*this < other); } bool is_null() const { return ptr == nullptr; } int use_count() const { return ref_count ? *ref_count : 0; } T* get() const { return ptr; } private: T* ptr; int* ref_count; void dispose() { if (ref_count) { --(*ref_count); if (*ref_count == 0) { delete ptr; delete ref_count; } ptr = nullptr; ref_count = nullptr; } } }; ``` 该shared_ptr实现了拷贝构造函数、拷贝赋值运算符、析构函数、箭头运算符、解引用运算符、相等运算符、不等运算符、比较运算符、is_null()方法、use_count()方法和get()方法。 在构造函数中,初始化指针ptr为nullptr,引用计数ref_count为nullptr。在拷贝构造函数中,ptr和ref_count被复制,并且引用计数加1。在析构函数中,如果引用计数不为0,就减1,如果减到0,就删除指针ptr和引用计数ref_count。在赋值运算符中,先dispose旧的shared_ptr,然后复制新的shared_ptr,最后增加引用计数。在箭头运算符和解引用运算符中,返回指针ptr。在相等运算符和不等运算符中,比较指针ptr。在比较运算符中,比较指针ptr。在is_null()方法中,判断指针ptr是否为nullptr。在use_count()方法中,返回引用计数ref_count的值,如果为nullptr,则返回0。在get()方法中,返回指针ptr
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值