本文介紹c++的四種智能指針,其中後三種是c++11新增加的,auto _ptr已被棄用。
要編譯c++11,需要安裝g++-4.8
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
sudo apt-get instal gcc-4.8
sudo apt-get install g++-4.8
編譯時指定標准:
g++-4.8 -std=c++11
auto_ptr詳細請參考這裡
auto_ptr是為了推動RAII而加入到c++標准的第一個智能指針,它實現了最基本的資源管理,不過與其他類型不同的是,auto_ptr是沒有復制語義的,它在復制時實現的其實是移動語義,復制和賦值auto_ptr時會默認改變所管理資源的所有權,基於這個原因,它也不能在stl容器中使用,因為容器內的元素必需支持可復制和可賦值。另外還有一個限制它使用范圍的因素是它的析構函數默認調用delete,而且無法重載,所以不能支持數組等對象。
class A{ public: A(int i) :ival(i){ printf("create %d \n",ival); } ~A(){ printf("delete %d \n", ival); } int getvalue(){ return ival;} private: int ival; }; auto_ptr<A> ptr1(new A(1)); auto_ptr<A> ptr2(new A(2)); assert(ptr1->getvalue()==1); assert(ptr2->getvalue()==2); ptr1 = ptr2; assert(ptr2.get ()==NULL); // now ptr2 is NULL
unique_ptr詳細請參考這裡
由於auto_ptr存在各種問題,c++11中unique_ptr華麗登場替換了auto_ptr,它們所做的事情基本一樣,不過unique_ptr不支持復制語義,只支持移動語義,所以無法執行普通的復制或賦值操作(返回將要被銷毀的unique_ptr時例外),但是可以進行移動構造賦值操作,說白了就是復制的話需要顯示move。另外unique_ptr可以重載刪除器,使其支持數組等類型。
unique_ptr<A> ptr1(new A(1)); unique_ptr<A> ptr2(new A(2)); ptr1 = ptr2; //error ptr1 = move(ptr2); //right, ptr2 is NULL assert(ptr2==NULL) unique_ptr<A[]> ptr3(new A[2]{3,4}); //array assert(ptr3[0].getvalue()==3); assert(ptr3[1].getvalue()==4);
shared_ptr 詳細請參考這裡
通常概念下的智能指針指的是shared_ptr,它允許共享資源,使用引用計數記錄資源被幾個指針共享。調用release(),析構函數或者被復制賦值時,原來管理的資源的引用計數都會減1,計數為0時釋放資源。
shared_ptr<A> ptr1(new A(1)); shared_ptr<A> ptr2(new A(2)); assert(ptr1->getvalue()==1); assert(ptr1.use_count()==1); assert(ptr2->getvalue()==2); assert( ptr2.use_count())==1); ptr1 = ptr2; assert(ptr1.use_count()==2) assert(ptr2.use_count()==2) assert(ptr1->getvalue()==2); assert(ptr2->getvalue()==2);
weak_ptr詳細請參考這裡
使用shared相互引用時會出現資源無法釋放的情況,比如:
class B; class A { public: shared_ptr<B> pb_value; ~A() { cout<<"A delete\n"; } }; class B { public: shared_ptr<A> pa_value; ~B() { cout<<"B delete\n"; } }; shared_ptr<B> pb(new B()); shared_ptr<A> pa(new A()); pb->pa_value = pa; pa->pb_value = pb; assert(pa.use_count()==2) assert(pb.use_count()==2)
引用如下
當pa,pb析構後,引用計數都等於1,資源不會釋放。解決方法是將pa_value和pb_value中任意一個聲明為 weak_ptr類型。
week_ptr是對對象的一種弱引用,它不會增加對象的引用計數。week_ptr和shared_ptr之間可以相互轉換,shared_ptr可以直接賦值給week_ptr,week_ptr可通過調用lock函數來獲得shared_ptr(如果對象已經被釋放,則返回一個空的shared_ptr)。
weak_ptr<A> pa_value;
修改後pb->pa_value=pa 不會增加pa的計數,pa計數為1,離開作用域後計數為0,pa正常釋放,於是pb計數也會減為0,正常釋放。
作者:coderkian
出處:http://www.cnblogs.com/coderkian/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。