共享指針 (shared_ptr) 是現(xiàn)在的 Boost 庫中提供的,并且應(yīng)該是將來 C++1x 的標(biāo)準(zhǔn)庫中提供的一個模板類。在此之前,ISO/IEC 14882:2003 標(biāo)準(zhǔn)庫 <memory> 中的“自動指針 (auto_ptr)”也有類似的功能。顯然 shared_ptr 要比 auto_ptr 從功能上來說應(yīng)該強(qiáng)大一些。這篇文章主要介紹 shared_ptr 的最基本用法和注意事項,相當(dāng)于入門級多一點點。
1. shared_ptr 的功能shared_ptr 主要的功能是,管理動態(tài)創(chuàng)建的對象的銷毀。它的基本原理就是記錄對象被引用的次數(shù),當(dāng)引用次數(shù)為 0 的時候,也就是最后一個指向某對象的共享指針析構(gòu)的時候,共享指針的析構(gòu)函數(shù)就把指向的內(nèi)存區(qū)域釋放掉。 共享指針對象重載了 operator* 和 operator-> , 所以你可以像通常的指針一樣使用它。這部分不再贅述。 2. shared_ptr 所在庫2.1. 對于 Visual C++ 2010目前,Visual C++ 2010 的 <memory> 庫里,已經(jīng)包含了 shared_ptr 模板類,也就是說,你可以直接這樣寫: #include <memory> 2.2. 對于其它支持 ISO/IEC 14882:2003 標(biāo)準(zhǔn)的編譯器而 GNU G++ 的標(biāo)準(zhǔn)庫中還沒有支持(畢竟是將來的標(biāo)準(zhǔn)),如果在 G++ 中想使用 shared_ptr, 還是得用到 Boost 庫,就是說,在 G++ 里,你得這樣寫: #include <boost/shared_ptr.hpp> 3. shared_ptr 的構(gòu)造保險起見,你應(yīng)該僅從以下幾種途徑構(gòu)造一個共享指針(以下例子中若沒特殊說明,T 就代表共享指針?biāo)赶虻膶ο蟮念愋停?/p> 3.0. 使用空參數(shù)構(gòu)造函數(shù)構(gòu)造也就是說,你可以直接定義一個 shared_ptr 而不指定構(gòu)造函數(shù)的內(nèi)容:
這樣做的話,ptr 的意義就相當(dāng)于一個 NULL 指針。當(dāng)你試圖在一個空指針上做類似于 *ptr 或者 ptr->xx 之類的東西的時候,應(yīng)該會收到異常的。 3.1. 直接從 new 操作符的返回值構(gòu)造用代碼來表示,就是可以這樣使用:
3.2. 使用復(fù)制構(gòu)造函數(shù)(或等號重載),從其它 shared_ptr 的對象構(gòu)造一種顯然的情況是這樣的:
還有,shared_ptr 可以當(dāng)作函數(shù)的參數(shù)傳遞,或者當(dāng)作函數(shù)的返回值返回,這個時候其實也相當(dāng)于使用復(fù)制構(gòu)造函數(shù)。 3.3. 從 shared_ptr 提供的類型轉(zhuǎn)換 (cast) 函數(shù)的返回值構(gòu)造shared_ptr 也可以類型轉(zhuǎn)換,有關(guān)類型轉(zhuǎn)換的詳情參見下面的 5. 此處假設(shè) B 是 A 的子類,那么,在 C 語言中 B 的指針當(dāng)然是可以轉(zhuǎn)換成 A 的指針的。在共享指針里,應(yīng)該這樣做:
4. shared_ptr 的“賦值”shared_ptr 也可以直接賦值,但是必須是賦給相同類型的 shared_ptr 對象,而不能是普通的 C 指針或 new 運(yùn)算符的返回值。當(dāng)共享指針 a 被賦值成 b 的時候,如果 a 原來是 NULL, 那么直接讓 a 等于 b 并且讓它們指向的東西的引用計數(shù)加 1; 如果 a 原來也指向某些東西的時候,如果 a 被賦值成 b, 那么原來 a 指向的東西的引用計數(shù)被減 1, 而新指向的對象的引用計數(shù)加 1. 就是說以下代碼是允許的:
shared_ptr 的對象在構(gòu)造之后,可以被賦予空值,此時使用的應(yīng)該是 reset() 函數(shù),如:
當(dāng)然理論上也可以這樣寫:
5. shared_ptr 的類型轉(zhuǎn)換shared_ptr 有兩種類型轉(zhuǎn)換的函數(shù),一個是 static_pointer_cast, 一個是 dynamic_pointer_cast. 其實用法真的和 C++ 提供的 static_cast 和 dynamic_cast 很像,再結(jié)合 3.3. 的代碼和以下類似的代碼,幾乎沒什么好講的:
6. 從 shared_ptr 的對象獲得傳統(tǒng) C 指針很簡單,可以這樣用:
7. shared_ptr 的常見的其它用法比如,“我想讓一個已經(jīng)構(gòu)造好的共享指針,丟棄掉原來所指的對象(或者讓其引用計數(shù)減 1),然后指向一個新的 new 出來的對象,該怎么辦?”參考如下代碼:
8. shared_ptr 的錯誤用法一定要注意,本節(jié)所述所有方法,都是錯誤的! 8.1. 在“中途”使用傳統(tǒng) C 指針構(gòu)造共享指針所謂在中途,指的就是不從 new 的返回值直接構(gòu)造共享指針,比如從 this 指針構(gòu)造自己的共享指針等。 8.2. 從一個對象的傳統(tǒng) C 指針,構(gòu)造出兩個或以上的共享指針其實這種和 8.1. 也是類似的,或者說,這種情況是 8.1. 的一種具體情況,比如,下面的代碼是錯誤的:
這樣的話,ptr1 和 ptr2 的引用計數(shù)是單獨(dú)算的,它們?nèi)我庖粋€對象在析構(gòu)的時候,都會銷毀 a 所指的對象,所以,這個對象會被“銷毀兩次”。 9. shared_ptr 的局限有關(guān)運(yùn)行效率的問題在這里就不討論了。其它方面,shared_ptr 的構(gòu)造要求比較高,如果對象在創(chuàng)建的時候沒有使用共享指針存儲的話,之后也不能用共享指針管理這個對象了。如果有引用循環(huán) (reference cycle), 也就是對象 a 有指向?qū)ο?b 的共享指針,對象 b 也有指向?qū)ο?a 的共享指針,那么它們都不會被析構(gòu)。當(dāng)然的,shared_ptr 也沒有辦法和 Garbage Collecting 比較,畢竟如果運(yùn)行庫能夠干預(yù),還是有算法可以檢查到引用循環(huán)的。(例如求強(qiáng)連通分量的算法。) 尤其,在類的成員函數(shù)的編寫的時候,有時我們經(jīng)常希望得到“自己”的共享指針,但是這往往是無法得到的。此時也不能夠從 this 指針構(gòu)造自己的共享指針(參見 8.1.),所以有時很憋悶。 10. 總結(jié)實際上上面這么多注意事項,中心思想就是一個:讓 shared_ptr 正確地記錄對象被引用次數(shù)。如果能悟出一點 shared_ptr 的工作原理,基本上不會弄出太危險的事情來。 轉(zhuǎn)載于:http:///2344/
boost::shared_ptr的特點: 和前面介紹的boost::scoped_ptr相比,boost::shared_ptr可以共享對象的所有權(quán),因此其使用范圍基本上沒有什么限制(還是有一些需要遵循的使用規(guī)則,下文中介紹),自然也可以使用在stl的容器中。另外它還是線程安全的,這點在多線程程序中也非常重要。 boost::shared_ptr的使用規(guī)則: boost::shared_ptr并不是絕對安全,下面幾條規(guī)則能使我們更加安全的使用boost::shared_ptr:
|
|