使用情景:當(dāng)類對象被 shared_ptr 管理時,需要在類自己定義的函數(shù)里把當(dāng)前類對象作為參數(shù)傳給其他函數(shù)時,這時需要傳遞一個 shared_ptr ,否則就不能保持 shared_ptr 管理這個類對象的語義(因為有一個 raw pointer 指向這個類對象,而 shared_ptr 對類對象的這個引用沒有計數(shù),很有可能 shared_ptr 已經(jīng)把類對象資源釋放了,而那個調(diào)用函數(shù)還在使用類對象——顯然,這肯定會產(chǎn)生錯誤)。
很好奇這個模板類的實現(xiàn)。
先看看怎么使用:
對一個類 A ,當(dāng)我們希望使用 shared_ptr 來管理其類對象時,而且需要在自己定義的函數(shù)里把類對象 shared_ptr (為什么不用普通指針,當(dāng)我們使用智能指針管理資源時,必須統(tǒng)一使用智能指針,而不能在某些地方使用智能指針某些地方使用 raw pointer ,否則不能保持智能指針的語義,從而產(chǎn)生各種錯誤)傳給其他函數(shù)時,可以讓類 A 從 enable_shared_from_this 繼承:
class A : public boost::enable_shared_from_this<A> {
};
然后在類 A 中需要傳遞類對象本身 shared_ptr 的地方使用 shared_from_this 函數(shù)來獲得指向自身的 shared_ptr 。
一個非常有代表性的例子:
另《Beyond the C++ Standard Library》 shared_ptr 節(jié)也有很簡單明了的例子。
實現(xiàn)原理:
首先要考慮的是:在類對象本身當(dāng)中不能存儲類對象本身的 shared_ptr ,否則類對象 shared_ptr 永遠也不會為0了,從而這些資源永遠不會釋放,除非程序結(jié)束。
其次:類對象肯定是外部函數(shù)通過某種機制分配的,而且一經(jīng)分配立即交給 shared_ptr 管理(再次強調(diào)一遍:給 shared_ptr 管理的資源必須在分配時交給 shared_ptr ),而且以后凡是需要共享使用類對象的地方必須使用這個 shared_ptr 當(dāng)作右值來構(gòu)造產(chǎn)生或者拷貝產(chǎn)生另一個 shared_ptr 從而達到共享使用的目的。
有了以上兩點的限制,要實現(xiàn)我們的目標(biāo)(即在類對象內(nèi)部使用類對象的 shared_ptr )有以下兩種方案:
1、類對象的外部 shared_ptr 作為函數(shù)參數(shù)傳給類的需要引用類對象自身的函數(shù)——顯然,這種方法很丑陋,而且并不是所有的情況都可行(如在外部 shared_ptr 不可見的作用域中就不行);
2、類對象自身存儲某種信息,在需要自身 shared_ptr 時來產(chǎn)生一個臨時的 shared_ptr 。
顯然,第2種方法更優(yōu)雅(對于用戶來說),關(guān)鍵是信息怎么存儲?
對了, weak_ptr !
實際上, boost 中就是這樣實現(xiàn)的。
但現(xiàn)在的問題是:何時初始化這個 weak_ptr ?因為類對象生成時還沒有生成相應(yīng)的用來管理這個對象的 shared_ptr 。
boost 1.39.0 中是這樣實現(xiàn)的:
首先生成類 A :會依次調(diào)用 enable_shared_from_this 的構(gòu)造函數(shù)(定義為 protected ),以及類 A 的構(gòu)造函數(shù)。在調(diào)用 enable_shared_from_this 的構(gòu)造函數(shù)時,會初始化定義在 enable_shared_from_this 中的 weak_ptr (調(diào)用其默認(rèn)構(gòu)造函數(shù)),這時這個 weak_ptr 是無效的(或者說不指向任何對象)。
接著:外部程序會把指向類 A 對象的指針作為初始化參數(shù)來初始化一個 shared_ptr 。
現(xiàn)在來看看 shared_ptr 是如何初始化的, shared_ptr 定義了如下構(gòu)造函數(shù):
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p )
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}
里面調(diào)用了 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 ) );
}
}
里面又調(diào)用了 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 的一個觀察者。
這時,當(dāng)類對象本身需要自身的 shared_ptr 時,就可以從這個 weak_ptr 來生成一個了。
posted on 2012-05-20 15:37
chatler 閱讀(617)
評論(0) 編輯 收藏 引用 所屬分類:
GP_STL