1. 程式人生 > 實用技巧 >C++中的智慧指標

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;
}