shared_ptr&scoped_ptr&weak_ptr

RAII - Resource Acquisition Is Initialization

  获得一个资源的时候,不管这个资源是对象、内存、文件句柄或者其它什么,你都要在一个对象的构造函数中获得它, 并且在该对象的析构函数中释放它。当你创建资源的时候将它放入封装类对象构造函数(new出来的指针立即放入shared_ptr析造函数里), 当该对象离开作用域时,对象析构函数会自动销毁资源。

shared_ptr

  在shard_ptr使用中经常会发现,一个对象会有两次被析构的情况。其实这种是因为那个对象指针被两次当成shard_ptr构造函数里的参数。一定要避免这种现象。考虑如下代码:

1 {
2     int* pInt = new int(14);
3     boost::shared_ptr<int> temp1(pInt);
4     assert(temp1.use_count() == 1);      // 用一个指针初始化temp1,temp1认为pInt只被它拥有。所以这个指针被引用1次
5 
6     boost::shared_ptr<int> temp2(pInt); // 用一个指针初始化temp2,temp2认为pInt只被它拥有。所以这个指针被引用1次
7     assert(temp2.use_count() == 1);
8 
9     }   // temp1,temp2都离开作用域,它们都销毁pInt. pInt被销毁了两次!系统终于崩溃了 -_-

  正确的做法是将原始指针赋给智能指针后,以后的操作都要针对智能指针了.

1 {
2     boost::shared_ptr<int> temp1(new int(14)); // 资源获取即初始化
3     assert(temp1.use_count() == 1);
4 
5     boost::shared_ptr<int> temp2(temp1);
6     assert(temp2.use_count() == 2);
7 
8 }   // temp1,temp2都离开作用域,引用次数变为0,指针被销毁

  如果资源的创建销毁不是以new,delete的方式创建销毁怎么办?shared_ptr也可以指定删除器:

 1 // FileCloser.h FileCloser删除器  
 2 class FileCloser
 3 {
 4     public:
 5     void operator()(FILE *pf)
 6     {
 7         if (pf)
 8         {
 9           fclose(pf);
10         }
11     }
12 };
13 
14 // 某实现文件
15 {
16     boost::shared_ptr<FILE> fp(fopen(pszConfigFile, "r"), FileCloser());    // 指定调用FileCloser函数对象销毁资源
17 }

weak_ptr

   weak_ptr必须用shared_ptr/weak_ptr初始化,用lock()获取指针。使用lock后,会返回一个shared_ptr的临时栈变量,把ptr引用计数加1,从而可以放心使用,而不用担心在使用过程中ptr会被其它线程给释放。

  

引用计数管理

  shared_ptr、weak_ptr的引用计数管理可简化为,两种指针都内含同一个引用计数管理器,如下:

  

  refcount_为shared_ptr使用,weak_count_为weak_ptr使用。当shared_ptr构造时,refcount_+1,析构时refcount-1,并且检察weak_count_是否为0;当weak_ptr构造时,weak_count_+1,析构时weak_count_-1。

  当refcount_weak_count_均为0时,把controlblok删除。shared_ptr、weak_ptr成员变量均为如下结构。

  

scoped_ptr

  scoped_ptr无法共享,无拷贝构造函数和赋值函数。用于局部使用。

原文地址:https://www.cnblogs.com/tekkaman/p/3308624.html