enable_shared_from_this

http://blog.csdn.net/cangyingzhijia/article/details/12586317
使用情景 :当类对象被 shared_ptr 管理时,须要在类本身定义的函数里把当前类对象做为参数传给其余函数时,这时须要传递一个 shared_ptr ,不然就不能保持 shared_ptr 管理这个类对象的语义( 由于有一个 raw pointer 指向这个类对象,而 shared_ptr 对类对象的这个引用没有计数,颇有可能 shared_ptr 已经把类对象资源释放了,而那个调用函数还在使用类对象——显然,这确定会产生错误 )。
 
很好奇这个模板类的实现。
 
先看看怎么使用
 
对一个类 A ,当咱们但愿使用 shared_ptr 来管理其类对象时,并且须要在本身定义的函数里把类对象 shared_ptr ( 为何不用普通指针,当咱们使用智能指针管理资源时,必须统一使用智能指针,而不能在某些地方使用智能指针某些地方使用 raw pointer ,不然不能保持智能指针的语义,从而产生各类错误 )传给其余函数时,可让类 A 从 enable_shared_from_this 继承:
 
class A : public boost::enable_shared_from_this<A> {
};
 
而后在类 A 中须要传递类对象自己 shared_ptr 的地方使用 shared_from_this 函数来得到指向自身的 shared_ptr 。
 
一个很是有表明性的例子:
 
 
另《Beyond the C++ Standard Library》 shared_ptr 节也有很简单明了的例子。
 
实现原理
 
首先要考虑的是:在类对象自己当中不能存储类对象自己的 shared_ptr ,不然类对象 shared_ptr 永远也不会为0了,从而这些资源永远不会释放,除非程序结束。
 
其次:类对象确定是外部函数经过某种机制分配的,并且一经分配当即交给 shared_ptr 管理( 再次强调一遍:给 shared_ptr 管理的资源必须在分配时交给 shared_ptr  ),并且之后凡是须要共享使用类对象的地方必须使用这个 shared_ptr 看成右值来构造产生或者拷贝产生另外一个 shared_ptr 从而达到共享使用的目的。
 
有了以上两点的限制,要实现咱们的目标( 即在类对象内部使用类对象的 shared_ptr  )有如下两种方案:
 
一、类对象的外部 shared_ptr 做为函数参数传给类的须要引用类对象自身的函数——显然,这种方法很丑陋,并且并非全部的状况均可行( 如在外部 shared_ptr 不可见的做用域中就不行 );
 
二、类对象自身存储某种信息,在须要自身 shared_ptr 时来产生一个临时的 shared_ptr 。
 
显然,第2种方法更优雅(对于用户来讲),关键是信息怎么存储?
 
对了, weak_ptr !
 
实际上, boost 中就是这样实现的。
 
但如今的问题是:什么时候初始化这个 weak_ptr ?由于类对象生成时尚未生成相应的用来管理这个对象的 shared_ptr 。
 
boost 1.39.0 中是这样实现的:
 
首先生成类 A :会依次调用 enable_shared_from_this 的构造函数(定义为 protected ),以及类 A 的构造函数。在调用 enable_shared_from_this 的构造函数时,会初始化定义在 enable_shared_from_this 中的 weak_ptr (调用其默认构造函数),这时这个 weak_ptr 是无效的(或者说不指向任何对象)。
 
接着:外部程序会把指向类 A 对象的指针做为初始化参数来初始化一个 shared_ptr 。
 
如今来看看 shared_ptr 是如何初始化的, shared_ptr 定义了以下构造函数:
 
template<class Y>
    explicit shared_ptr( Y * p ): px( p ), pn( p ) 
    {
        boost::detail::sp_enable_shared_from_this( this, p, p );
    }
 
里面调用了  boost::detail::sp_enable_shared_from_this :
 
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 ) );
    }
}
 
里面又调用了 enable_shared_from_this 的 _internal_accept_owner :
 
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 );
        }
    }
 
而在这里对 enable_shared_from_this 的成员 weak_ptr 进行拷贝赋值,使得整个 weak_ptr 做为类对象  shared_ptr 的一个观察者。
 
这时,当类对象自己须要自身的 shared_ptr 时,就能够从这个 weak_ptr 来生成一个了。
 
原来如此。
本站公众号
   欢迎关注本站公众号,获取更多信息