weak_ptr 類模板
Introduction 簡(jiǎn)介
Synopsis 概要
Members 成員
Free Functions 自由函數(shù)
Frequently Asked Questions 常見問(wèn)題
weak_ptr 類模板存儲(chǔ)一個(gè)引向已被 shared_ptr 管理的對(duì)象的 "weak reference"(弱引用)。為了訪問(wèn)這個(gè)對(duì)象,一個(gè) weak_ptr 可以利用 shared_ptr 的構(gòu)造函數(shù)或成員函數(shù) lock 轉(zhuǎn)換為 shared_ptr。當(dāng)最后一個(gè)指向?qū)ο蟮?shared_ptr 消失,而對(duì)象也被刪除后,從一個(gè)引向已被刪除對(duì)象的 weak_ptr 實(shí)例獲取 shared_ptr 的企圖就會(huì)失?。簶?gòu)造函數(shù)會(huì)拋出一個(gè) boost::bad_weak_ptr 類型的異常,而 weak_ptr::lock 會(huì)返回一個(gè) empty shared_ptr。
每一個(gè) weak_ptr 都符合 C++ 標(biāo)準(zhǔn)庫(kù)的 CopyConstructible 和 Assignable 的必要條件,并因此能夠用于標(biāo)準(zhǔn)庫(kù)容器。因?yàn)樘峁┝吮容^操作,因此 weak_ptr 可以和標(biāo)準(zhǔn)庫(kù)中的關(guān)聯(lián)式容器一起工作。
weak_ptr 的操作絕不會(huì)拋出異常。
這個(gè)類模板被 T 參數(shù)化,T 是被指向的對(duì)象的類型。
相對(duì)于 shared_ptr,weak_ptr 提供了一個(gè)非常有限的操作子集,因?yàn)樵诙嗑€程程序中訪問(wèn)它所存儲(chǔ)的指針是非常危險(xiǎn)的,甚至有時(shí)在一個(gè)單線程程序中也是不安全的(也就是說(shuō),它可能引起未定義行為)。姑且假設(shè) weak_ptr 有一個(gè)返回 raw pointer(裸指針)的 get 成員函數(shù),考慮下面這個(gè)無(wú)辜的代碼片段:
shared_ptr<int> p(new int(5)); weak_ptr<int> q(p);
// some time later
if(int * r = q.get()) { // use *r }
設(shè)想在 if 之后,但是又恰恰在 r 被使用之前,另一個(gè)線程執(zhí)行了語(yǔ)句 p.reset() 。這樣 r 就成了一個(gè) dangling pointer(懸掛指針)。
解決這個(gè)問(wèn)題的方案是從 q 創(chuàng)建一個(gè)臨時(shí)的 shared_ptr:
shared_ptr<int> p(new int(5)); weak_ptr<int> q(p);
// some time later
if(shared_ptr<int> r = q.lock()) { // use *r }
這樣,r 就持有一個(gè)引向 q 所指向的對(duì)象的引用。即使在其它線程中執(zhí)行了 p.reset() ,那個(gè)對(duì)象也會(huì)繼續(xù)活著,直到 r 離開作用域或者被 reset。通過(guò)獲得一個(gè)指向這個(gè)對(duì)象的 shared_ptr,我們可以有效地保住它不被析構(gòu)。
namespace boost {
template<class T> class weak_ptr {
public: typedef T element_type;
weak_ptr();
template<class Y> weak_ptr(shared_ptr<Y> const & r); weak_ptr(weak_ptr const & r); template<class Y> weak_ptr(weak_ptr<Y> const & r);
~weak_ptr();
weak_ptr & operator=(weak_ptr const & r); template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r); template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
long use_count() const; bool expired() const; shared_ptr<T> lock() const;
void reset(); void swap(weak_ptr<T> & b); };
template<class T, class U> bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b); }
typedef T element_type;
提供模板參數(shù) T 的類型。
weak_ptr();
作用:構(gòu)造一個(gè) empty weak_ptr。
后置條件:use_count() == 0 。
拋出:無(wú)。
template<class Y> weak_ptr(shared_ptr<Y> const & r); weak_ptr(weak_ptr const & r); template<class Y> weak_ptr(weak_ptr<Y> const & r);
作用:如果 r 為 empty,構(gòu)造一個(gè) empty weak_ptr,否則,構(gòu)造一個(gè)和 r shares ownership(共享所有權(quán))的 weak_ptr,就像存儲(chǔ)了 r 中所存儲(chǔ)指針的一個(gè)拷貝。
后置條件:use_count() == r.use_count() 。
拋出:無(wú)。
~weak_ptr();
作用:銷毀這個(gè) weak_ptr,但對(duì)于所存儲(chǔ)指針?biāo)赶虻膶?duì)象沒有作用。
拋出:無(wú)。
weak_ptr & operator=(weak_ptr const & r); template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r); template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);
作用:等價(jià)于 weak_ptr(r).swap(*this) 。
拋出:無(wú)。
注意:實(shí)現(xiàn)可以自由地經(jīng)由不同的手段達(dá)到其效果(以及隱含的保證),而不創(chuàng)建臨時(shí)變量。
long use_count() const;
返回:如果 *this 為 empty,返回 0,否則,返回和 *this share ownership(共享所有權(quán))的 shared_ptr 對(duì)象的數(shù)目。
拋出:無(wú)。
注意:use_count() 達(dá)不到必要的效率。只用于調(diào)試和測(cè)試的目的。而不要用于產(chǎn)品代碼。
bool expired() const;
返回:use_count() == 0 。
拋出:無(wú)。
注意:expired() 可能比 use_count() 更快。
shared_ptr<T> lock() const;
返回:expired()? shared_ptr<T>(): shared_ptr<T>(*this) 。
拋出:無(wú)。
void reset();
作用:等價(jià)于 weak_ptr().swap(*this) 。
void swap(weak_ptr & b);
作用:交換兩個(gè)智能指針的內(nèi)容。
拋出:無(wú)。
template<class T, class U> bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
返回:一個(gè)未確定值,以致于
-
operator< 是一個(gè)嚴(yán)格意義上的 C++ 標(biāo)準(zhǔn) 25.3
[lib.alg.sorting] 中描述的 weak ordering(弱順序);
-
等值關(guān)系通過(guò) operator< 來(lái)定義,
!(a < b) && !(b < a) ,在這種情況下,當(dāng)且僅當(dāng)兩個(gè) weak_ptr 實(shí)例 share ownership(共享所有權(quán))或者都為 empty 時(shí),兩個(gè) weak_ptr 相等。
拋出:無(wú)。
注意:允許 weak_ptr 對(duì)象在關(guān)聯(lián)式容器中作為鍵值使用。
template<class T> void swap(weak_ptr<T> & a, weak_ptr<T> & b)
作用:等價(jià)于 a.swap(b) 。
拋出:無(wú)。
注意:與 std::swap 的接口匹配。為泛型編程提供幫助。
問(wèn):一個(gè)對(duì)象能不能在自己的構(gòu)造函數(shù)內(nèi)創(chuàng)建一個(gè)指向自己的 weak_ptr 呢?
答:不能。weak_ptr 只能從一個(gè) shared_ptr 創(chuàng)建,而在對(duì)象構(gòu)造的時(shí)候指向?qū)ο蟮?shared_ptr 還不存在。即使你能創(chuàng)建一個(gè)指向 this 的臨時(shí) shared_ptr,它也會(huì)在構(gòu)造函數(shù)結(jié)尾處離開作用域,而所有的 weak_ptr 實(shí)例立馬過(guò)期。
解決方案是把構(gòu)造函數(shù)做成 private 的,并配備一個(gè)返回 shared_ptr 的工廠函數(shù)。
class X { private:
X();
public:
static shared_ptr<X> create() { shared_ptr<X> px(new X); // create weak pointers from px here return px; } };
|