C++中的智慧指標
C++的智慧指標:
智慧指標本質上是一個類,當超出了類的作用域時,會自動呼叫解構函式釋放資源。
好處:可以避免出現申請的空間在函式結束時忘記釋放,造成記憶體洩漏。
1. auto_ptr:(採用所有權模式,已被C++11拋棄)
auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”));
auto_ptr<string> p2;
p2 = p1; //auto_ptr不會報錯.
此時不會報錯,p2剝奪了p1的所有權,但是當程式執行時訪問p1將會報錯。所以auto_ptr的缺點是:存在潛在的記憶體崩潰問題!
2. unique_ptr(替換auto_ptr)
unique_ptr實現獨佔式擁有或嚴格擁有概念,保證同一時間內只有一個智慧指標可以指向該物件。
採用所有權模式:
unique_ptr<string> p3 (new string ("auto")); //#4
unique_ptr<string> p4; //#5
p4 = p3;//此時會報錯!!
編譯器認為p4=p3非法,避免了p3不再指向有效資料的問題。因此,unique_ptr比auto_ptr更安全。
特別地,當程式試圖將一個 unique_ptr 賦值給另一個時,如果源 unique_ptr 是個臨時右值,編譯器允許這麼做。
C++有一個標準庫函式std::move(),讓你能夠將一個unique_ptr賦給另一個。
unique_ptr<string> ps1, ps2;
ps1 = demo("hello");
ps2 = move(ps1);
ps1 = demo("alexia");
cout << *ps2 << *ps1 << endl;
3. shared_ptr
shared_ptr實現共享式擁有概念。
多個智慧指標可以指向相同物件,該物件和其相關資源會在“最後一個引用被銷燬”時候釋放。
它使用計數機制來表明資源被幾個指標共享,可以通過use_count()來檢視資源的所有者個數。
除了可以通過new來構造,還可以通過傳入auto_ptr, unique_ptr,weak_ptr來構造。
當呼叫release()時,當前指標會釋放資源所有權,計數減一。
當計數等於0時,資源會被釋放。
成員函式:
use_count 返回引用計數的個數
unique 返回是否是獨佔所有權( use_count 為 1)
swap 交換兩個 shared_ptr 物件(即交換所擁有的物件)
reset 放棄內部物件的所有權或擁有物件的變更, 會引起原有物件的引用計數的減少
get 返回內部物件(指標), 由於已經過載了()方法, 因此和直接使用物件是一樣的.
如 shared_ptr<int> sp(new int(1)); sp 與 sp.get()是等價的。
4. weak_ptr
weak_ptr指向一個 shared_ptr 管理的物件,提供了對管理物件的一個訪問手段。
weak_ptr 設計的目的是為配合 shared_ptr,只可以從一個 shared_ptr 或另一個 weak_ptr 物件構造,且它的構造和析構不會引起引用記數的增加或減少。
weak_ptr是用來解決shared_ptr相互引用時的死鎖問題,如果說兩個shared_ptr相互引用,那麼這兩個指標的引用計數永遠不可能下降為0,資源永遠不會釋放。
它是對物件的一種弱引用,和shared_ptr之間可以相互轉化,shared_ptr可以直接賦值給它,它可以通過呼叫lock函式來獲得shared_ptr。
#include <iostream>
using namespace std;
int main()
{
shared_ptr<int> p0(new int(5));
shared_ptr<int> p1;
shared_ptr<int> p2;
p1 = p0;
p2 = p1;
cout << *p1 << endl; // output: 5
cout << p1.unique() << endl; // 是否獨佔所有權 output: 0
cout << p0.use_count() << endl; // output: 3
cout << p1.use_count() << endl; // output: 3
cout << p2.use_count() << endl; // output: 3
p1.reset(); // shared_ptr p1放棄對資源的所有權
cout << p2.use_count() << endl; // output: 2
cout << p1.get() << endl; // output: 00000000
cout << *p2 << endl; // output: 5
cout << p2.unique() << endl; // 是否獨佔所有權 output: 0
weak_ptr<int> p3(p2); // 使用shared_ptr型別的p2複製構造一個shared_ptr
cout << p2.use_count() << endl; // weak_ptr不增加引用計數 output: 2
cout << *p3.lock() << endl; // 使用lock函式獲取物件 output: 5
weak_ptr<int> p4 = p2; // 使用shared_ptr型別的p2賦值構造一個shared_ptr
cout << p2.use_count() << endl; // weak_ptr不增加引用計數 output: 2
cout << *p4.lock() << endl; // 使用lock函式獲取物件 output: 5
p3.reset(); // weak_ptr p3放棄對資源的引用
cout << p3.lock() << endl; // output: 00000000
cout << p2.use_count() << endl; // output: 2
p2.reset(); // shared_ptr p2放棄對資源的所有權
cout << p2.get() << endl; // output: 00000000
cout << p0.use_count() << endl; // output: 1
cout << *p4.lock() << endl; // output: 5
p0.reset(); // shared_ptr p0放棄對資源的所有權, 此時資源的引用計數為0,會被自動釋放
cout << p4.lock() << endl; // output: 00000000 當所有的shared_ptr釋放後,資源會被釋放,指向該資源的weak_ptr也無法訪問該資源,weak_ptr不對資源擁有所有權
return 0;
}