? ? ? ? 在C++11中有四種智能指針,auto_ptr,shared-ptr,unique_ptr和weak-ptr,其中auto_ptr有許多不足之處,在C++11中已經建議廢棄使用。
1.?shared_ptr
? ??std::shared_ptr智能指針可以通過共享指向對象的所有權,從而實現對對象的動態管理。std::shared_ptr一般不會擁有對象,相反,所有指向對象的std::shared_ptr指針合作起來確保在對象不需要時析構被調用。當最后一個指向對象的std::shared_ptr不再指向該對象時(比如該std::shared_ptr被銷毀或者指向別的對象),這個std::shared_ptr會銷毀它指向的對象。就像垃圾回收一樣,用戶自己不用關心被指向對象的生存周期,同時對析構來說,對象的析構時間是確定的。
? ?一個std::shared_ptr可以通過查詢指向對象的引用計數來得到它是否是最后一個指針,引用計數是一個和資源關聯的值,它記錄了有多少std::shared_ptr指向該資源。std::shared_ptr構造函數中會增加引用計數,析構函數匯總減小引用計數(通常是這樣---見下面),拷貝復制操作兩者都執行。(假如sp1和sp2指向不同的對象,操作“sp1=sp2;”會修改sp1,指向sp2,結果就是原來sp指向的對象的引用計數減少了,同時sp2指向的對象的引用計數增加了。)當一個std::shared_ptr 指針看到對象的引用計數在指向完減一操作后變為0時,那么沒有std::shared_ptr指向該對象了,于是std::shared_ptr將會銷毀它。
2.?unique_ptr
? ? 通常可以認為std::unique_ptr和原始指針有相同的尺寸,并且對于多數操作(包括解引用),它和原始指針有幾乎相同的指令。這意味著你可以在內存和cpu緊張的地方使用它,如果普通的原始指針對你夠快夠用的話,那么std::unique_ptr幾乎也是夠用的。
? ? std::unique_ptr實現了獨享所有權的語義。一個非空的std::unique_ptr總是擁有它所指向的資源。轉移一個std::unique_ptr將會把所有權也從源指針轉移給目標指針(源指針被置空)。拷貝一個std::unique_ptr將不被允許,因為如果你拷貝一個std::unique_ptr,那么拷貝結束后,這兩個std::unique_ptr都會指向相同的資源,它們都認為自己擁有這塊資源(所以都會企圖釋放)。因此std::unique_ptr是一個僅能移動(move_only)的類型。當指針析構時,它所擁有的資源也被銷毀。默認情況下,資源的析構是伴隨著調用std::unique_ptr內部的原始指針的delete操作的。
??std::unique_ptr通常出現兩種形式。一種是單個對象(std::unique_ptr<T>),另一種是數組(std::unique_ptr<T[]>)。標準庫提供了一個可以管理new分配數組的unique_ptr版本,為了用一個unique_ptr管理動態數組,我們必須在對象類型后面跟一對方括號。
unique_ptr<int[]>up(new int[10]);
up.realese();//自動用delete[]銷毀其指針。
當unique_ptr指向數組時我們不能使用點和箭頭運算符,而是用下標來訪問數組中的元素:
for(size_ti=0;i I != 10; ++i)
up[i]=i;
unique_ptr<T[]>u //u指向一個類型為T的動態分配的數組
unique_ptr<T[]>u (p) //u指向內置指針p所指向的動態分配的數組。P必須能轉換為類型T*
u[i] //返回位置i的元素
3.?weak-ptr
? ?有時候,我們需要一個靈巧指針可以像std::shared_ptr一樣方便,但又不參與管理被指對象的所有權。換句話說,需要一個像std::shared_ptr但又不影響對象引用計數的指針。這類指針會有一個std::shared_ptr沒有的問題:被指的對象有可能已經被銷毀。一個良好的靈巧指針應該能處理這種情況,通過跟蹤什么時候指針會懸浮,比如在被指對象不復存在的時候。這正是std::weak_ptr這類型靈巧指針所能做到的。
??weak_ptr是一種不控制所指向對象生存期的智能指針,它指向一個shared_ptr管理的對象。將一個weak_ptr綁定到shared_ptr不會改變shared_ptr的引用計數。一旦最后一個指向對象的shared_ptr被銷毀,對象就會被釋放,即使有weak_ptr指向對象,對象還是會被釋放。
當我們創建一個weak_ptr時,要用一個shared_ptr來初始化它:
auto p=make_shared_ptr<int>(42);
weak_ptr<int>wp(p); //wp弱共享p,p的引用計數未改變
由于對象可能不存在,我們不能使用weak_ptr直接訪問對象,而必須調用lock().此函數檢查weak_ptr指向的對象是否存在。如果存在lock則返回一個指向共享對象的shared_ptr,同時該對象的引用計數會增加。
? ?
if(shared_ptr<int> np= wp.lock())
{
}
? ? ? std::weak_ptr可以和std::shared_ptr 一起解決引用計數的循環引用問題。
? ? ?具體可參考《std::shared_ptr 和 std::weak_ptr的用法以及引用計數的循環引用問題》
參考文獻:
1.?c++11 條款19:使用std::shared_ptr來進行共享所有權的資源管理
2.?c++11 條款20:使用std::weak_ptr作為一個類似std::share_ptr但卻能懸浮的指針
3.?c++11 條款18: 使用std::unique_ptr來進行獨享所有權的資源管理
4.?C++ 智能指針shared-ptr,unique_ptr和weak-ptr
5. ? ?? [C++11]_[初級]_[shared_ptr的使用場景]
6. ? ? ?[C++11]_[初級]_[unique_ptr的使用場景]
7. ? ?? [C++11]_[初級]_[weak_ptr的使用場景]
8. ? ?【C++11新特性】 C++11智能指針之unique_ptr
9. ?? 【C++11新特性】 C++11智能指針之shared_ptr
10 . ?【C++11新特性】 C++11智能指針之weak_ptr