C++智能指針:unique_ptr

1、智能指針概念

智能指針是基於RAII機制實現的類(模板),具有指針的行爲(重載了operator*與operator->操作符),可以“智能”地銷燬其所指對象。C++11中有unique_ptr、shared_ptr與weak_ptr等智能指針,可以對動態資源進行管理


2、unique_ptr的基本操

unique_ptr“唯一”擁有其所指對象,同一時刻只能有一個unique_ptr指向給定對象(通過禁止拷貝語義、只有移動語義來實現)。

unique_ptr指針本身的生命週期:從unique_ptr指針創建時開始,直到離開作用域。離開作用域時,若其指向對象,則將其所指對象銷燬(默認使用delete操作符,用戶可指定其他操作)。

unique_ptr指針與其所指對象的關係:在智能指針生命週期內,可以改變智能指針所指對象,如創建智能指針時通過構造函數指定、通過reset方法重新指定、通過release方法釋放所有權、通過移動語義轉移所有權。


3、 unique_ptr的基本操作

  1. //智能指針的創建  
  2. unique_ptr<int> u_i; //創建<span style="font-family:Arial,Helvetica,sans-serif">“</span><span style="font-family:Arial,Helvetica,sans-serif">空智能指針”</span>  
  3. u_i.reset(new int(3)); //"綁定”動態對象  
  4. unique_ptr<int> u_i2(new int(4));//創建時指定動態對象  
  5. //所有權的變化  
  6. int *p_i = u_i2.release(); //釋放所有權  
  7. unique_ptr<string> u_s(new string("abc"));  
  8. unique_ptr<string> u_s2 = std::move(u_s); //所有權轉移(通過移動語義),u_s所有權轉移後,變成“空指針”  
  9. u_s2=nullptr;//顯式銷燬所指對象,同時智能指針變爲空指針。與u_s2.reset()等價  


4、unique_ptr的使用場景

(1) 動態資源的異常安全保證(利用其RAII特性):

  1. void foo()  
  2. {//不安全的代碼  
  3.     X *px = new X;  
  4.     // do something, exception may occurs  
  5.     delete px; // may not go here  
  6. }  
  1. void foo()  
  2. {//異常安全的代碼。無論是否異常發生,只要px指針成功創建,其析構函數都會被調用,確保動態資源被釋放  
  3.     unique_ptr<X> px(new X);  
  4.     // do something,  
  5. }  
(2) 返回函數內創建的動態資源

  1. unique_ptr<X> foo()  
  2. {  
  3.     unique_ptr<X> px(new X);  
  4.     // do something  
  5.     return px; //移動語義  
  6. }  
(3) 可放在容器中(彌補了auto_ptr不能作爲容器元素的缺點)

方式一:

  1. vector<unique_ptr<string>> vs { new string{“Doug”}, new string{“Adams”} };  
方式二:

  1. vector<unique_ptr<string>>v;  
  2. unique_ptr<string> p1(new string("abc"));  
  3. v.push_back(std::move(p1));//這裏需要顯式的移動語義,因爲unique_ptr並無copy語義  

(4) 管理動態數組,因爲unique_ptr有unique_ptr<X[]>重載版本,銷燬動態對象時調用delete[]

  1. unique_ptr<int[]> p (new int[3]{1,2,3});  
  2. p[0] = 0;// 重載了operator[]  


5、自定義資源刪除操作(Deleter):

unique_ptr默認的資源刪除操作是delete/delete[],若需要,可以進行自定義:

  1. void end_connection(connection *p) { disconnect(*p); } //資源清理函數  
  2. unique_ptr<connection, decltype(end_connection)*> //資源清理器的“類型”  
  3.         p(&c, end_connection);// 傳入函數名,會自動轉換爲函數指針  


6 auto_ptr與unique_ptr

在C++11環境下,auto_ptr被看做“遺留的”,他們有如下區別:

auto_ptr有拷貝語義,拷貝後源對象變得無效;unique_ptr則無拷貝語義,但提供了移動語義

auto_ptr不可作爲容器元素,unique_ptr可以作爲容器元素

auto_ptr不可指向動態數組(儘管不會報錯,但不會表現出正確行爲),unique_ptr可以指向動態數組


發佈了66 篇原創文章 · 獲贊 34 · 訪問量 17萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章