Smart Pointer

boost 提供的智能指针包括scoped_ptr,scoped_array,shared_ptr,shared_array,weak_ptr, intrusive_ptr;
6种智能指针都是异常安全的。智能指针使用了代理模式。

boost 定义的智能指针:

1. scoped_ptr

① 私有化拷贝构造函数和=运算符,禁止拷贝构造和拷贝赋值,不能转移(move/&&)

② 可以自动转换成bool类型和c++11的nullptr类型,但是两个scoped_ptr不能做比较操作,因为==和!=操作符被私有化。

③ get()方法可以取到原始指针,但是不要做delete操作,因为析构时会delete原始指针,对原始指针做delete操作,会导致delete空指针或悬空指针,发生未定义行为。

④ 提供*和->操作符,可以像普通指针一样操作。

2. scoped_array

① 私有化拷贝构造函数和=运算符,禁止拷贝构造和拷贝赋值,不能转移(move/&&)

② 可以自动转换成bool类型和c++11的nullptr类型,但是两个scoped_ptr不能做比较操作,因为==和!=操作符被私有化。

③ get()方法可以取到原始指针,但是不要做delete[]操作,因为析构时会delete[]原始指针,对原始指针做delete[]操作,会导致delete[]空指针或悬空指针,发生未定义行为。

④ 不提供*和->,但是提供了[]操作符,可以像普通数组一样使用下标操作,但不提供begin(),end()迭代操作函数。

3. shared_ptr

① 使用引用计数管理原始指针。引用计数为0时自动删除原始指针。

② 提供*和->操作。

③ 支持拷贝构造和拷贝赋值。

④ 提供==和!=操作符,两个shared_ptr之间可以相互比较。

⑤ 提供<操作符,可以被用于标准关联容器set和map

⑥ 可以定制删除器。

⑦ 与内置类型提供相同的线程安全等级:多线程可以同时读取,但是其他访问形式为未定义。

⑧ 提供make_shared工厂函数构造shared_ptr对象。

4. shared_array

① 可用shared_ptr或者vector代替,不推荐使用。

5. weak_ptr

① 弱指针,与shared_ptr协同工作。

② 可以使用shared_ptr对象构造,但是不会增加shared_ptr计数。

③ 不提供*和->操作符,无法对资源进行更改读取操作。

④ 提供lock方法,可以取得观测的shared_ptr对象。

6. intrusive_ptr

① 类似于shared_ptr,使用计数管理的智能指针,但是需要手动添加计数管理函数:void instrusive_ptr_add_ref(T*)和void instrusive_ptr_release(T*)。

② 构造函数instrusive_ptr(T*,bool),当bool为false时,相当于weak_ptr。

③ 可以继承instrusive_ref_counter,该类为引用计数类,提供自动引用计数管理的功能,继承该类的类,自动获得引用计数管理的功能。

enable_shared_from_this


类模板。继承该类的派生类可以从调用shared_from_this成员函数产生管理this指针的shared_ptr。

① 使用场景:当类对象被 shared_ptr 管理时,且需要在类的成员函数里把当前类对象作为参数传给其他函数时,这时需要传递一个 shared_ptr ,否则就不能保持shared_ptr 管理这个类对象的语义(因为有一个 raw pointer 指向这个类对象,而 shared_ptr 对类对象的这个引用没有计数,很有可能 shared_ptr 已经把类对象资源释放了,而那个调用函数还在使用类对象——显然,这肯定会产生错误)。
            例如:boost::asio中各种异步操作,传入成员函数为回调函数。

② 实现原理:

a. 

  1. template<class Y> explicit shared_ptr( Y * p ): px( p ), pn()
  2. {
  3.     boost::detail::sp_pointer_construct( this, p,pn )
  4. }


b.

  1. template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T >* ppx, Y * pboost::detail::shared_count & pn )
  2. {
  3.     boost::detail::shared_count( p ).swap( pn );                       
  4.     boost::detail::sp_enable_shared_from_this( ppx, p, p );
  5. }

c. 


  1. template< class X, class Y, class T inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppxY const * py,  boost::enable_shared_from_this< T > const * pe)
  2. {
  3.     if( pe != 0 )
  4.     {
  5.         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
  6.     }
  7. }

d.  

  1. template<class X, class Y> void _internal_accept_owner(shared_ptr<X> const * ppxY * py ) const
  2. {
  3.     if( weak_this_.expired() )
  4.     {
  5.         weak_this_ = shared_ptr<T>( *ppx, py );
  6.     }
  7. }

e. 

  1. shared_ptr<T const> shared_from_this() const
  2. {
  3.     shared_ptr<T const> p( weak_this_ );
  4.     BOOST_ASSERT( p.get() == this );
  5.     return p;
  6. }

③ 注意事项:

a. 不能在对象的构造函数中使用shared_from_this()函数。

b. 先需要调用enable_shared_from_this类的构造函数,接着调用对象的构造函数,最后需要调用shared_ptr类的构造函数初始化enable_shared_from_this的成员变量weak_this_。然后才能使用shared_from_this()函数。  

c. 如果程序中使用了智能指针shared_ptr,最好程序中统一使用智能指针,避免使用原始指针,以免出现错误。

C++11 定义的智能指针:

1. unique_ptr:

结合了scoped_ptr和scoped_array的功能,能够代理new和new []对象。

scoped_ptr的异同:

同:

① 拷贝构造函数=delete,禁止拷贝构造。

② 可以自动转换成bool类型和nullptr。

异:

① 两个scoped_ptr之间不能做比较,而两个unique_tpr之间是可以比较的。

② scoped_ptr不能定制删除器,而unique_ptr可以定制删除器。

③ scoped_ptr不能转移,而unique_ptr是可以转移的。

scoped_array的异同:

同:

异:

2. shared_ptr

boost::shared_ptr相同。


@boost笔记系列总结自罗剑锋的《Boost库完全开发指南》第三版、Boost 1.61.0 Library Documentation、boost 1.51 源码。

10-01 03:09