c++11之智能指針


本文介紹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,正常釋放。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM