1、shared_ptr<T>解决什么问题?
auto_ptr有个局限,拥有权转移。这往往不符合我们的需求,有时候我们期望,多个资源管理对象可以共享一个资源,当引用计数为0的时候,执行delete。shared_ptr就是为了解决这个问题。
2、shared_ptr怎么解决这个问题?和auto_ptr类似,除此之外,还有几点需要注意:
3、增加一个字段为引用计数,当引用计数为0的时候,执行delete。引用计数字段不能放在资源管理类中,为什么?
假设放到资源管理类中,每个资源管理对象都有一个refCount字段,共享一个资源的资源管理对象的refCount取值一样,但是怎么保持一致呢?因为这些对象之间没有关联。同时注意:这里不能把refCount字段声明为static,因为static意味着资源管理类的所有对象共享refCount,而当前的要求是一部分对象共享一个refCount,另一部分对象共享另一个refCount。因此,引用计数要和资源绑定在一起。也就是说,这里需要两层封装:第一层是u_ptr<T>类,对资源封装,增加refCount字段,负责delete。第二层是shared_ptr<T>,对u_ptr<T>封装,判断u_ptr对象的引用计数为0,执行u_ptr的析构方法,间接释放资源。
4、有些情况下,当引用计数为0 的时候,我们不想执行delete,而是其他操作,因此,还需要一个删除器,和引用计数同样的道理,删除器应该放在u_ptr中,这个删除器就是指向方法的指针。
5、auto_ptr的copy构造和copy赋值,要转移拥有权。而shared_ptr的copy构造,引用计数加1,copy赋值对原对象的引用计数减1,引用计数为0,执行delete,同时对rhs的引用计数加1。
6、析构的时候,引用计数减1,引用计数为0,才执行delete。
7、示例代码如下(不完整,只有一部分):
1 template <typename T> 2 class u_ptr 3 { 4 template <typename T> friend class shared_ptr; 5 private: 6 u_ptr(T* ptr):_ptr(ptr),refCount(1) 7 { 8 } 9 10 ~u_ptr() 11 { 12 delete _ptr; 13 } 14 15 T* _ptr; 16 int refCount; 17 }; 18 19 template <typename T> 20 class shared_ptr 21 { 22 public: 23 shared_ptr(T* ptr):_u_ptr_ptr(new u_ptr<T>(ptr)) 24 { 25 } 26 27 shared_ptr(shared_ptr<T>& rhs) 28 { 29 _u_ptr_ptr= rhs._u_ptr_ptr; 30 ++_u_ptr_ptr->refCount; 31 } 32 33 shared_ptr& operator=(shared_ptr<T>& rhs) 34 { 35 if(this!=&rhs) 36 { 37 if(--_u_ptr_ptr->refCount ==0) 38 { 39 delete _u_ptr_ptr; 40 } 41 _u_ptr_ptr= rhs._u_ptr_ptr; 42 ++_u_ptr_ptr->refCount; 43 } 44 return *this; 45 } 46 47 ~shared_ptr() 48 { 49 if(--_u_ptr_ptr->refCount ==0) 50 { 51 delete _u_ptr_ptr; 52 } 53 } 54 55 private: 56 u_ptr<T>* _u_ptr_ptr; 57 };