1. 程式人生 > >智慧指標 weak_ptr

智慧指標 weak_ptr

weak_ptr:
 weak_ptr是為了配合shared_ptr而引入的一種智慧指標,它更像是shared_ptr的一個助手而不是智慧指標,因為它不具有普通指標的行為,沒有過載operator*和->,它的最大作用在於協助shared_ptr工作,像旁觀者那樣觀測資源的使用情況.
用法:
 weak_ptr被設計為與shared_ptr共同工作,可以從一個shared_ptr或者另一個weak_ptr物件構造,獲得資源的觀測權。但weak_ptr沒有共享資源,它的構造不會引起指標引用計數的增加。
 使用weak_ptr的成員函式use_count()可以觀測資源的引用計數,另一個成員函式expired()的功能等價於use_count()==0,但更快,表示被觀測的資源(也就是shared_ptr的管理的資源)已經不復存在。
 weak_ptr可以使用一個非常重要的成員函式lock()從被觀測的shared_ptr獲得一個可用的shared_ptr物件, 從而操作資源。但當expired()==true的時候,lock()函式將返回一個儲存空指標的shared_ptr.
例項:
#include <boost/smart_ptr.hpp>
#include <boost/make_shared.hpp>
using namespace boost;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
 shared_ptr<int> sp(new int(10));
 assert(sp.use_count() == 1);
 weak_ptr<int> wp(sp); //從shared_ptr建立weak_ptr
 assert(wp.use_count() == 1);
 if (!wp.expired())//判斷weak_ptr觀察的物件是否失效
 {
  shared_ptr<int> sp2 = wp.lock();//獲得一個shared_ptr
  *sp2 = 100;
  assert(wp.use_count() == 2);
 }
 assert(wp.use_count() == 1);
 return 0;
}

獲得this的shared_ptr
 weak_ptr的一個重要用途是獲得this指標的shared_ptr,使物件自己能夠生產shared_ptr管理自己;物件使用weak_ptr觀測this指標,這並不影響引用計數,在需要的時候就呼叫lock()函式,返回一個符合要求的shared_ptr共外界使用.
 這個解決方案被實現為一個慣用法,在標頭檔案<boost/enable_shared_from_this.hpp>定義了一個助手類enable_shared_from_this<T>,它的宣告摘要如下:
template<class T>
class enable_shared_from_this
{
public:
 shared_ptr<T> shared_from_this();
}
使用的時候只需要讓像被shared_ptr管理的類從它繼承即可,成員函式shared_from_this()會返回this的shared_ptr.例如:
#include <boost/make_shared.hpp>
#include <boost/enable_shared_from_this.hpp>
using namespace boost;
using namespace std;
class self_shared: public enable_shared_from_this<self_shared>
{
public:
 self_shared(int n):x(n){}
 int x;
 void print()
 {cout<<" self_shared:"<<x<<endl;}
};
int _tmain(int argc, _TCHAR* argv[])
{
 shared_ptr<self_shared> sp = make_shared<self_shared>(314);
 sp->print();
 shared_ptr<self_shared> p = sp->shared_from_this();
 p->x = 1000;
 p->print();
 return 0;
}

注意:千萬不能從一個普通物件(非shared_ptr)使用shared_from_this()獲去shared_ptr,例如
self_shared ss;
shared_ptr<self_shared> p = ss.shared_from_this();//錯誤!
在執行時會導致shared_ptr析構時企圖刪除一個棧上分配的物件,發生未定義行為。