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.
- template<class Y> explicit shared_ptr( Y * p ): px( p ), pn()
- {
- boost::detail::sp_pointer_construct( this, p,pn )
- }
b.
- template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T >* ppx, Y * p, boost::detail::shared_count & pn )
- {
- boost::detail::shared_count( p ).swap( pn );
- boost::detail::sp_enable_shared_from_this( ppx, p, p );
- }
c.
- template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe)
- {
- if( pe != 0 )
- {
- pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
- }
- }
d.
- template<class X, class Y> void _internal_accept_owner(shared_ptr<X> const * ppx, Y * py ) const
- {
- if( weak_this_.expired() )
- {
- weak_this_ = shared_ptr<T>( *ppx, py );
- }
- }
e.
- shared_ptr<T const> shared_from_this() const
- {
- shared_ptr<T const> p( weak_this_ );
- BOOST_ASSERT( p.get() == this );
- return p;
- }
③ 注意事项:
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 源码。