C 智慧型指標 auto ptr 詳解

2021-09-06 17:33:56 字數 2830 閱讀 3154

auto_ptr 是c++標準庫提供的類模板,auto_ptr物件通過初始化指向由new建立的動態記憶體,它是這塊記憶體的擁有者,一塊記憶體不能同時被分給兩個擁有者。當auto_ptr物件生命週期結束時,其析構函式會將auto_ptr物件擁有的動態記憶體自動釋放。即使發生異常,通過異常的棧展開過程也能將動態記憶體釋放。auto_ptr不支援new 陣列。

#include

1) 建構函式

1] 將已存在的指向動態記憶體的普通指標作為引數來構造

int* p = new int(33);

auto_ptrapi(p);

2] 直接構造智慧型指標

auto_ptr< int > api( new int( 33 ) );

2) 拷貝構造

利用已經存在的智慧型指標來構造新的智慧型指標

auto_ptr< string > pstr_auto( new string( "brontosaurus" ) );

auto_ptr< string > pstr_auto2( pstr_auto );  //利用pstr_auto來構造pstr_auto2

因為一塊動態記憶體智慧型由乙個智慧型指標獨享,所以在拷貝構造或賦值時都會發生擁有權轉移的過程。在此拷貝構造過程中,pstr_auto將失去對字串記憶體的所有權,而pstr_auto2將其獲得。物件銷毀時,pstr_auto2負責記憶體的自動銷毀。

3) 賦值

利用已經存在的智慧型指標來構造新的智慧型指標

auto_ptr< int > p1( new int( 1024 ) );

auto_ptr< int > p2( new int( 2048 ) );

p1 = p2;

在賦值之前,由p1 指向的物件被刪除。賦值之後,p1 擁有int 型物件的所有權。該物件值為2048。 p2 不再被用來指向該物件。

通常的指標在定義的時候若不指向任何物件,我們用null給其賦值。對於智慧型指標,因為建構函式有預設值0,我們可以直接定義空的auto_ptr如下:

auto_ptr< int > p_auto_int;  //不指向任何物件

因為auto_ptr的所有權獨有,所以下面的**會造成混亂。

int* p = new int(0);

auto_ptrap1(p);

auto_ptrap2(p);

因為ap1與ap2都認為指標p是歸它管的,在析構時都試圖刪除p, 兩次刪除同乙個物件的行為在c++標準中是未定義的。所以我們必須防止這樣使用auto_ptr。

1) 按值傳遞時,函式呼叫過程中在函式的作用域中會產生乙個區域性物件來接收傳入的auto_ptr(拷貝構造),這樣,傳入的實參auto_ptr就失去了其對原物件的所有權,而該物件會在函式退出時被區域性auto_ptr刪除。如下例:

void f(auto_ptrap)

auto_ptrap1(new int(0));

f(ap1);

cout<<*ap1; //錯誤,經過f(ap1)函式呼叫,ap1已經不再擁有任何物件了。

2) 引用或指標時,不會存在上面的拷貝過程。但我們並不知道在函式中對傳入的auto_ptr做了什麼,如果當中某些操作使其失去了對物件的所有權,那麼這還是可能會導致致命的執行期錯誤。

結論:const reference是智慧型指標作為引數傳遞的底線。

原因很簡單,delete 表示式會被應用在不是動態分配的指標上這將導致未定義的程式行為。

1) get()

int* p = new int(33);

cout << "the adress of p: "<< p << endl;

auto_ptrap1(p);

cout << "the adress of ap1: " << &ap1 << endl;

cout << "the adress of the object which ap1 point to: " << ap1.get() << endl;

輸出如下:

the adress of p: 00481e00

the adress of ap1: 0012ff68

the adress of the object which ap1 point to: 00481e00

第一行與第三行相同,都是int所在的那塊記憶體的位址。第二行是ap1這個類物件本身所在記憶體的位址。

2) reset()

重新設定auto_ptr指向的物件。類似於賦值操作,但賦值操作不允許將乙個普通指標指直接賦給auto_ptr,而reset()允許。如下例:

auto_ptr< string > pstr_auto( new string( "brontosaurus" ) );

pstr_auto.reset( new string( "long -neck" ) );

在例子中,重置前pstr_auto擁有"brontosaurus"字元記憶體的所有權,這塊記憶體首先會被釋放。之後pstr_auto再擁有"long -neck"字元記憶體的所有權。

注:reset(0)可以釋放物件,銷毀記憶體。

3) release()

返回auto_ptr指向的那個物件的記憶體位址,並釋放對這個物件的所有權。

用此函式初始化auto_ptr時可以避免兩個auto_ptr物件擁有同乙個物件的情況(與get函式相比)。

例子如下:

auto_ptr< string > pstr_auto( new string( "brontosaurus" ) );

auto_ptr< string > pstr_auto2( pstr_auto.get() ); //這是兩個auto_ptr擁有同乙個物件

auto_ptr< string > pstr_auto2( pstr_auto.release() ); //release可以首先釋放所有權

C 智慧型指標 auto ptr

智慧型指標 auto ptr vc版本 擁有權管理和轉移 當乙個智慧型指標給另乙個智慧型指標初始化的時候,兩個智慧型指標將會同時指向乙個空間,這樣在物件析構的時候,會導致一塊空間釋放多次的問題,所以乙個物件從始至終只能擁有乙個智慧型指標,這樣就保證不會乙個物件多次釋放的問題.我們讓指標給指標初始化的...

C 智慧型指標(auto ptr)

智慧型指標 在c 中使用堆記憶體是非常頻繁的操作,堆記憶體的申請和釋放都由程式設計師自己管理。使用普通指標,容易造成堆記憶體洩露,二次釋放等問題,使用智慧型指標能更好的管理堆記憶體。c 11中引入了智慧型指標的概念,方便管理堆記憶體。棧 堆區別 棧 系統開闢 系統釋放 堆 手動開闢 手動釋放 設計 ...

C 智慧型指標auto ptr

template class auto ptr 建構函式 templateinline auto ptr auto ptr t p pointee p 拷貝建構函式 templateinline auto ptr auto ptr auto ptr rhs pointee rhs.release t...