1. 程式人生 > >C++智慧指標之unique_ptr

C++智慧指標之unique_ptr

C++智慧指標之auto_ptr一文中得知:在使用auto_ptr時,可能會不經意的將多個auto_ptr指向同一塊記憶體,造成auto_ptr銷燬釋放時多次釋放同一塊記憶體。為了解決該問題,本文引出了unique_ptr。

顧名思義,unique是唯一的意思。說明它跟auto_ptr有點類似,就是同時只能有一個智慧指標物件指向某塊記憶體,與auto_ptr不同,unique_ptr還有些其他特性:

  1. unique_ptr無法進行復制構造與賦值操作,會編譯報錯
auto_ptr<int> ap(new int(88 );
auto_ptr<
int> one (ap) ; // ok auto_ptr<int> two = one; //ok unique_ptr<int> ap(new int(88 ); unique_ptr<int> one (ap) ; // 編譯會出錯 unique_ptr<int> two = one; // 編譯會出錯
  1. unique_ptr可以進行移動構造和移動賦值操作

程式碼解釋:這裡是顯式的所有權轉移,即:將up所指的記憶體轉給uPtr2,而up不再擁有該記憶體。

unique_ptr<int> up(new int(
88 ); unique_ptr<int> uPtr2 = std:move(up); //移動構造
  1. unique_ptr可以作為返回值,用於從某個函式中返回動態申請記憶體的所有權
unique_ptr<int> GetVal( )
{
  unique_ptr<int> up(new int(88 );
  return up;
}
unique_ptr<int> uPtr = GetVal();   //ok

程式碼解釋:返回unique_ptr型別的變數,本質上是移動拷貝,等價於上面講解的2中的程式碼。

  1. unique_ptr可做為容器元素,但是必須通過移動語義實現
vector<unique_ptr<int> > vec; //定義unique_ptr型別的vector

unique_ptr<int> sp(new int(88) ); //定義unique_ptr型別的變數sp
vec.push_back(std::move(sp)); //使用移動語義,將sp插入到vec中

cout<<*sp<<endl; //error,因為sp新增到容器過程中,sp失效,sp自身報廢了。

vec.push_back(sp); // error,不使用移動語義新增編譯會失敗

總結:
從上面的例子可以看出:unique_ptr和auto_ptr真的非常類似。其實你可以這樣簡單的理解,auto_ptr是可以說你隨便賦值,但賦值完了之後原來的物件就不知不覺的報廢,搞得你莫名其妙;而unique就乾脆不讓你可以隨便去複製、賦值,如果實在想傳個值,必須顯式的說明記憶體轉移std:move一下。然後這樣傳值完了之後,之前的物件也同樣報廢了,只不過整個move你讓明顯的知道這樣操作後會導致之前的unique_ptr物件失效。