午夜视频在线网站,日韩视频精品在线,中文字幕精品一区二区三区在线,在线播放精品,1024你懂我懂的旧版人,欧美日韩一级黄色片,一区二区三区在线观看视频

分享

Boost智能指針:shared

 Frank__Library 2014-04-24
   共享指針 (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)容:

1
shared_ptr<T> ptr;

這樣做的話,ptr 的意義就相當(dāng)于一個 NULL 指針。當(dāng)你試圖在一個空指針上做類似于 *ptr 或者 ptr->xx 之類的東西的時候,應(yīng)該會收到異常的。

3.1. 直接從 new 操作符的返回值構(gòu)造

用代碼來表示,就是可以這樣使用:

1
shared_ptr<T> ptr(new T());

3.2. 使用復(fù)制構(gòu)造函數(shù)(或等號重載),從其它 shared_ptr 的對象構(gòu)造

一種顯然的情況是這樣的:

1
2
shared_ptr<T> ptr1(new T()); // 本行與 3.1. 中的構(gòu)造方法是一樣的
shared_ptr<T> ptr2(ptr1);    // 這就是使用復(fù)制構(gòu)造函數(shù)的方法,會讓引用計數(shù)加 1

還有,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)該這樣做:

1
2
shared_ptr<B> ptrb(new B());
shared_ptr<A> ptra( dynamic_pointer_cast<A>(ptrb) );

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. 就是說以下代碼是允許的:

1
2
3
shared_ptr<T> a(new T());
shared_ptr<T> b(new T());
a = b; // 此后 a 原先所指的對象會被銷毀,b 所指的對象引用計數(shù)加 1

shared_ptr 的對象在構(gòu)造之后,可以被賦予空值,此時使用的應(yīng)該是 reset() 函數(shù),如:

1
2
shared_ptr<T> a(new T());
a.reset(); // 此后 a 原先所指的對象會被銷毀,并且 a 會變成 NULL

當(dāng)然理論上也可以這樣寫:

1
2
shared_ptr<T> a(new T());
a = shared_ptr<T>(); // 相當(dāng)于給 a 賦一個新構(gòu)造的 shared_ptr, 也就是 NULL

5. shared_ptr 的類型轉(zhuǎn)換

shared_ptr 有兩種類型轉(zhuǎn)換的函數(shù),一個是 static_pointer_cast, 一個是 dynamic_pointer_cast. 其實用法真的和 C++ 提供的 static_cast 和 dynamic_cast 很像,再結(jié)合 3.3. 的代碼和以下類似的代碼,幾乎沒什么好講的:

1
2
3
shared_ptr<A> ptra;
shared_ptr<B> ptrb(new B());
ptra = dynamic_pointer_cast<A>(ptrb);

6. 從 shared_ptr 的對象獲得傳統(tǒng) C 指針

很簡單,可以這樣用:

1
2
shared_ptr<T> ptr(new T());
T *p = ptr.get(); // 獲得傳統(tǒng) C 指針

7. shared_ptr 的常見的其它用法

比如,“我想讓一個已經(jīng)構(gòu)造好的共享指針,丟棄掉原來所指的對象(或者讓其引用計數(shù)減 1),然后指向一個新的 new 出來的對象,該怎么辦?”參考如下代碼:

1
2
shared_ptr<T> ptr(new T());
ptr.reset(new T()); // 原來所指的對象會被銷毀

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. 的一種具體情況,比如,下面的代碼是錯誤的:

1
2
3
T *a = new T();
shared_ptr<T> ptr1(a);
shared_ptr<T> ptr2(a);

這樣的話,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:

  1. 避免對shared_ptr所管理的對象的直接內(nèi)存管理操作,以免造成該對象的重釋放
  2. shared_ptr并不能對循環(huán)引用的對象內(nèi)存自動管理(這點是其它各種引用計數(shù)管理內(nèi)存方式的通?。?。
  3. 不要構(gòu)造一個臨時的shared_ptr作為函數(shù)的參數(shù)。
    如下列代碼則可能導(dǎo)致內(nèi)存泄漏:
    void test()
    {
        foo(boost::shared_ptr<implementation>(new    implementation()),g());
    }
    正確的用法

    void test()
    {
        boost::shared_ptr<implementation> sp    (new implementation());
        foo(sp,g());
    }
    //當(dāng)函數(shù)g()拋異常的時候就會泄露了,這個是boost文檔上特地注明的標(biāo)準(zhǔn)bad Practices,Effective C++ Third Edition 條款17 有講到

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多