boost::weak_ptr和enable_shared_from_this
boost::weak_ptr和enable_shared_from_this
?
shared_ptr在我的實踐中使用很廣,在接口層面上,我基本都會默認的使用shared_ptr.而weak_ptr則很少使用;即便使用,也是間接的使用,例如使得class A繼承自boost::enable_shared_from_this,這樣A便具有了一個weak_ptr的成員對象,我便可以通過接口shared_from_this()得到一個boost::shared_ptr<A>的對象.
除此之外,在實踐中我幾乎沒有用到weak_ptr.到目前為止,我見到的對weak_ptr論述最好的是<<Beyond.the.C.plus.plus.Standard.Library.An.Introduction.to.Boost>>.本書給出了使用weak_ptr的三種場景: 打破遞歸的依賴關系;使用一個共享的資源而不需要共享所有權;避免懸空的指針.
后面兩種場景相對比較容易明白,對于第一種則相對模糊.最近幾天我相對仔細的研究了一下shared_ptr和weak_ptr的源代碼,給出我自己的理解如下.
?
weak_ptr是依附于shared_ptr的,所以首先要把shared_ptr弄清楚;另外,我認為boost::enable_shared_from_this是解釋遞歸的依賴關系的最好例子,所以使用這個實例解釋weak_ptr最好不過了.
?
shared_ptr的圖解
?
?
?
?
??? 如圖所示,3個智能指針對象sp1,sp2,sp3,共享同一個對象object和同一個計數器counter,當3個指針對象sp1,sp2,sp3聲明周期結束的時候,counter==0,object會被銷毀(當然,這個銷毀器本身可以由你定制).
shared_ptr的一個很大的特點是:counter==0,object會被銷毀;反之,如果counter總是不為0,那么object會成為永久對象,例如全局對象.
?
在http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html中給出了一個從this獲得shared_ptr的實例,答案是使用weak_ptr,問題是為什么是weak_ptr.
?
讓我們把這個問題重新說明一下:
struct X
{
???????? boost::shared_ptr<X>getX()
{
???????? boost::shared_ptr<X>r ;//????如何實現
???????? return r;
}
};
?
要得到X的智能指針,只是在對象指針是受shared_ptr保護的基礎上的,舉例如下:
void test_X()
{
???????? {
X x;
???????? ???????? boost::shared_ptr<X> px =x.getX();//錯誤
}
???????? {
X* x = new X();
boost::shared_ptr<X> px = x->getX();//錯誤
}
???????? {
boost::shared_ptr<X> ?x (new X());
boost::shared_ptr<X> px = x->getX();//正確
}
}
我們再回到原來的問題上,如何實現X::getX()函數.要構造X的智能指針,需要知道兩個信息,object的指針和object的計數器,顯然,指針本身可以通過this獲得,問題是如何獲得計數器,也即上面圖中的counter.很顯然,我們必須在X上存儲某些信息來得到計數器.
最先想到的也許是使用一個指向counter的指針存儲在X上面,這樣應該是可以的,但是存在一個問題:暴露了shared_ptr的實現細節,雖然shared_ptr是基于計數器的,但是這不屬于用戶需要知道的事情.最好的方式是讓shared_ptr本身來充當這個角色,這樣所有的實現細節就都封裝在shared_ptr內部了.
經過這樣改裝的shared_ptr的圖解是:
| ? |
| ? |
| ? |
???? 經過這樣包裝的object,問題立刻暴露出來:循環引用,造成object對象無法釋放,成為”全局對象”.很顯然,問題在于object本身參與了引用計數,也就是所有權的分享.我們需要的是不同于shared_ptr的這樣的一類共享指針:他們并不參與對象的所有權,只是能夠觀察到對象的所有權.而這正是weak_ptr的本質所在.
當然了,weak_ptr還有其他的特征:查看對象指針是否過期(這也是比裸指針好的地方).
循環引用的情況很罕見,這可能也是我在實際中很少使用weak_ptr的原因吧.
總結
以上是生活随笔為你收集整理的boost::weak_ptr和enable_shared_from_this的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Asterisk PBX 快速安装向导
- 下一篇: 如何健康学习到150岁?养生还是程序员专