C 中的智慧型指標 auto ptr

2021-09-08 17:49:44 字數 3406 閱讀 9710

實際上auto_ptr 僅僅是c++標準庫提供的乙個類模板,它與傳統的new/delete控制記憶體相比有一定優勢。使用它不必每次都手動呼叫delete去釋放記憶體。當然有利也有弊,也不是全然完美的。

本文從以下的8個方面來總結auto_ptr使用的大部分內容。

1. auto_ptr是什麼?

auto_ptr 是c++標準庫提供的類模板,auto_ptr物件通過初始化指向由new建立的動態記憶體,它是這塊記憶體的擁有者,一塊記憶體不能同一時候被分給兩個這樣擁有者(auto_ptr)。

當auto_ptr物件生命週期結束時。其析構函式會將auto_ptr物件擁有的動態記憶體自己主動釋放。即使發生異常,通過異常的棧展開過程也能將動態記憶體釋放。auto_ptr不支援new 陣列。

2. auto_ptr須要包括的標頭檔案?

#include

3. 初始化auto_ptr物件的方法?

1) 建構函式

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

int* p = new int(33);

auto_ptrapi(p);

這樣在api物件的生命週期結束的時候。會呼叫自身的析構函式,並delete來釋放擁有的記憶體,這樣我們就不須要寫以下的**:

delete 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

由於auto_ptr智慧型指標僅僅能獨享一塊動態記憶體,所以在拷貝構造或賦值時都會發生擁有權的轉移。

在此拷貝構造過程中,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 不再被用來指向該物件。

4. 空的auto_ptr 須要初始化嗎?

通常的指標在定義的時候若不指向不論什麼物件,我們用null給其賦值。

對於智慧型指標,由於建構函式有預設值0,我們能夠直接定義空的auto_ptr例如以下:

auto_ptr< int >p_auto_int;  //不指向不論什麼物件

5. 防止兩個auto_ptr物件擁有同乙個物件(一塊記憶體)

由於auto_ptr的全部權獨有。不能共享動態分配的記憶體。所以以下的**會造成混亂。

int* p = new int(0);

auto_ptrap1(p);

auto_ptrap2(p);

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

6. 警惕智慧型指標作為引數!

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

void f(auto_ptrap)

cout<<*ap;

}auto_ptrap1(new int(0));

f(ap1);

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

2) 出入的是引用或指標時,不會存在上面的拷貝過程。

但我們並不知道在函式中對傳入的auto_ptr做了什麼。假設其中某些操作使其失去了對物件的全部權。那麼這還是可能會導致致命的執行期錯誤。

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

7. auto_ptr不能初始化為指向非動態記憶體

原因非常easy。delete 表示式會被應用在不是動態分配的指標上這將導致沒有定義的程式行為。

8. auto_ptr經常使用的成員函式

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 theobject which ap1 point to: " << ap1.get() << endl;

輸出例如以下:

the adress of p: 00481e00

the adress of ap1: 0012ff68

the adress of the object which ap1point 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...