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的引用计数管理可简化为,两种指针都内含同一个引用计数管理器,如下:

  shared_ptr&scoped_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无法共享,无拷贝构造函数和赋值函数。用于局部使用。

你可能感兴趣的:(scope)