標籤:
在C++11中,引入了智能指標。主要有:unique_ptr, shared_ptr, weak_ptr。
這3種指標組件就是採用了boost裡的智能指標方案。很多有用過boost智能指標的朋友,很容易地就能發現它們之間的關間:
| std |
boost |
功能說明 |
| unique_ptr |
scoped_ptr |
獨佔指標對象,並保證指標所指對象生命週期與其一致 |
| shared_ptr |
shared_ptr |
可共用指標對象,可以賦值給shared_ptr或weak_ptr。 指標所指對象在所有的相關聯的shared_ptr生命週期結束時結束,是強引用。 |
| weak_ptr |
weak_ptr |
它不能決定所指對象的生命週期,引用所指對象時,需要lock()成shared_ptr才能使用。 |
C++11將boost裡的這一套納入了標準。
如下為範例程式碼:
//檔案 test-1.cpp#include <memory>#include <iostream>using namespace std;int main(){ unique_ptr<int> up1(new int(11)); unique_ptr<int> up2 = up1; //! 編譯時間會出錯 [1] cout << *up1 << endl; unique_ptr<int> up3 = move(up1); //! [2] cout << *up3 << endl; if (up1) cout << *up1 << endl; up3.reset(); //! [3] up1.reset(); shared_ptr<string> sp1(make_shared<string>("Hello")); shared_ptr<string> sp2 = sp1; cout << "*sp1:" << *sp1 << endl; cout << "*sp2:" << *sp2 << endl; sp1.reset(); cout << "*sp2:" << *sp2 << endl; weak_ptr<string> wp = sp2; //! [4] cout << "*wp.lock():" << *wp.lock() << endl; sp2.reset(); cout << "*wp.lock():" << *wp.lock() << endl; //! 運行時會出錯 return 0;}//編譯命令: g++ -std=c++11 test-1.cpp
[1]: unique_ptr 是禁止複製賦值的,始終保持一個 unique_ptr 管理一個對象。
[2]: unique_ptr 雖然不能賦值,但可以通過 move() 函數轉移對象的所有權。一旦被 move() 了,原來的 up1 則不再有效了。
[3]: reset() 可以讓 unique_ptr 提前釋放指標。
[4]: 由 shared_ptr 構造一個 weak_ptr。
shared_ptr 與 weak_ptr
如下面的樣本:
shared_ptr<string> s1(new string);shared_ptr<string> s2 = s1;weak_ptr<string> w1 = s2;
在記憶體中:
s1, s2, w1 都指向一個 ptr_manage 的對象。
在該對象中有 shared_ref_count 與 weak_ref_count 兩個域分別記錄引用它的 shared_ptr 與 weak_ptr 的個數。這個很容易辦到,只要在複製構造與賦值函數中對相當地引用值進行加1,在析構中減1即可。ptr_manage 中的 ptr 域存放真正的對象指標地址。
當 shared_ref_cnt 被減為0時,自動釋放 ptr 指標所指向的對象。當 shared_ref_cnt 與 weak_ref_cnt 都變成0時,才釋放 ptr_manage 對象。
如此以來,只要有相關聯的 shared_ptr 存在,對象就存在。weak_ptr 不影響對象的生命週期。當用 weak_ptr 訪問對象時,對象有可能已被釋放了,要先 lock()。
當執行:
s1.reset()
此時:
shared_ref_cnt 由2減成了1。
再執行:
s2.reset()
此時:
shared_ref_cnt 已被減到0了,ptr 所對應的object已被釋放,ptr 被清0。此時,ptr_manage 依舊保留。因為 w1 還需要引用它。
在最後,w1 也析構了的時候:
ptr_manage 中的 weak_ref_cnt 被減成0,最後連 ptr_manage 都釋放了。
C++11中的智能指標