《More Effective C++》ITEM M9中提到了auto_ptr,說(shuō)是當(dāng)異常產(chǎn)生的時(shí)候,怎樣釋放為對(duì)象分配的堆內(nèi)存,避免重復(fù)編寫(xiě)內(nèi)存釋放語(yǔ)句。
PS:這里書(shū)里面提到函數(shù)退出問(wèn)題,函數(shù)退出會(huì)清算棧內(nèi)存,不論是怎樣正常退出還是異常退出(唯一1種例外就是當(dāng)你調(diào)用 longjmp 時(shí)。Longjmp 的這個(gè)缺點(diǎn)是 C++率先支持異常處理的主要緣由)。建立在此基礎(chǔ)上我們才把對(duì)指針的刪除操作封裝到1個(gè)棧對(duì)象里面。這樣函數(shù)退出(異常或是正常)就會(huì)調(diào)用對(duì)象的析構(gòu)函數(shù),到達(dá)我們自動(dòng)清算所封裝指針指向的內(nèi)存的目的。
作為新手,不是很理解,記下來(lái),學(xué)習(xí)學(xué)習(xí)。
PS:C++11已不提倡用auto_ptr了,請(qǐng)看鏈接:http://www.cplusplus.com/reference/memory/auto_ptr/
Note: This class template is deprecated as of C++11. unique_ptr is
a new facility with a similar functionality, but with improved security (no fake copy assignments), added features (deleters)
and support for arrays. Seeunique_ptr for
additional information.
以下內(nèi)容copy自:http://blog.sina.com.cn/s/blog_7708265a01010lyv.html
auto_ptr 是C++標(biāo)準(zhǔn)庫(kù)提供的類(lèi)模板,auto_ptr對(duì)象通過(guò)初始化指向由new創(chuàng)建的動(dòng)態(tài)內(nèi)存,它是這塊內(nèi)存的具有者,1塊內(nèi)存不能同時(shí)被分給兩個(gè)具有者。當(dāng)auto_ptr對(duì)象生命周期結(jié)束時(shí),其析構(gòu)函數(shù)會(huì)將auto_ptr對(duì)象具有的動(dòng)態(tài)內(nèi)存自動(dòng)釋放。即便產(chǎn)生異常,通過(guò)異常的棧展開(kāi)進(jìn)程也能將動(dòng)態(tài)內(nèi)存釋放。auto_ptr不支持new 數(shù)組。
#include <memory>
1) 構(gòu)造函數(shù)
1] 將已存在的指向動(dòng)態(tài)內(nèi)存的普通指針作為參數(shù)來(lái)構(gòu)造
int* p = new int(33);
auto_ptr<int> api(p);
2] 直接構(gòu)造智能指針
auto_ptr< int > api( new int( 33 ) );
2) 拷貝構(gòu)造
利用已存在的智能指針來(lái)構(gòu)造新的智能指針
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
auto_ptr< string > pstr_auto2( pstr_auto );
由于1塊動(dòng)態(tài)內(nèi)存智能由1個(gè)智能指針獨(dú)享,所以在拷貝構(gòu)造或賦值時(shí)都會(huì)產(chǎn)生具有權(quán)轉(zhuǎn)移的進(jìn)程。在此拷貝構(gòu)造進(jìn)程中,pstr_auto將失去對(duì)字符串內(nèi)存的所有權(quán),而pstr_auto2將其取得。對(duì)象燒毀時(shí),pstr_auto2負(fù)責(zé)內(nèi)存的自動(dòng)燒毀。
3) 賦值
利用已存在的智能指針來(lái)構(gòu)造新的智能指針
auto_ptr< int > p1( new int( 1024 ) );
auto_ptr< int > p2( new int( 2048 ) );
p1 = p2;
在賦值之前,由p1 指向的對(duì)象被刪除。賦值以后,p1 具有int 型對(duì)象的所有權(quán)。該對(duì)象值為2048。 p2 不再被用來(lái)指向該對(duì)象。
通常的指針在定義的時(shí)候若不指向任何對(duì)象,我們用Null給其賦值。對(duì)智能指針,由于構(gòu)造函數(shù)有默許值0,我們可以直接定義空的auto_ptr以下:
auto_ptr< int > p_auto_int;
由于auto_ptr的所有權(quán)獨(dú)有,所以下面的代碼會(huì)造成混亂。
int* p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);
由于ap1與ap2都認(rèn)為指針p是歸它管的,在析構(gòu)時(shí)都試圖刪除p, 兩次刪除同1個(gè)對(duì)象的行動(dòng)在C++標(biāo)準(zhǔn)中是未定義的。所以我們必須避免這樣使用auto_ptr。
1) 按值傳遞時(shí),函數(shù)調(diào)用進(jìn)程中在函數(shù)的作用域中會(huì)產(chǎn)生1個(gè)局部對(duì)象來(lái)接收傳入的auto_ptr(拷貝構(gòu)造),這樣,傳入的實(shí)參auto_ptr就失去了其對(duì)原對(duì)象的所有權(quán),而該對(duì)象會(huì)在函數(shù)退出時(shí)被局部auto_ptr刪除。以下例:
void f(auto_ptr<int> ap)
{cout<<*ap;}
auto_ptr<int> ap1(new int(0));
f(ap1);
cout<<*ap1; //毛病,經(jīng)過(guò)f(ap1)函數(shù)調(diào)用,ap1已不再具有任何對(duì)象了。
2) 援用或指針時(shí),不會(huì)存在上面的拷貝進(jìn)程。但我們其實(shí)不知道在函數(shù)中對(duì)傳入的auto_ptr做了甚么,如果當(dāng)中某些操作使其失去了對(duì)對(duì)象的所有權(quán),那末這還是可能會(huì)致使致命的履行期毛病。
結(jié)論:const reference是智能指針作為參數(shù)傳遞的底線。
緣由很簡(jiǎn)單,delete 表達(dá)式會(huì)被利用在不是動(dòng)態(tài)分配的指針上這將致使未定義的程序行動(dòng)。
1) get()
返回auto_ptr指向的那個(gè)對(duì)象的內(nèi)存地址。以下例:
int* p = new int(33);
cout << "the adress of p: "<< p << endl;
auto_ptr<int> ap1(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
第1行與第3行相同,都是int所在的那塊內(nèi)存的地址。第2行是ap1這個(gè)類(lèi)對(duì)象本身所在內(nèi)存的地址。
2) reset()
重新設(shè)置auto_ptr指向的對(duì)象。類(lèi)似于賦值操作,但賦值操作不允許將1個(gè)普通指針指直接賦給auto_ptr,而reset()允許。以下例:
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
pstr_auto.reset( new string( "Long -neck" ) );
在例子中,重置前pstr_auto具有"Brontosaurus"字符內(nèi)存的所有權(quán),這塊內(nèi)存首先會(huì)被釋放。以后pstr_auto再具有"Long -neck"字符內(nèi)存的所有權(quán)。
注:reset(0)可以釋放對(duì)象,燒毀內(nèi)存。
3) release()
返回auto_ptr指向的那個(gè)對(duì)象的內(nèi)存地址,并釋放對(duì)這個(gè)對(duì)象的所有權(quán)。
用此函數(shù)初始化auto_ptr時(shí)可以免兩個(gè)auto_ptr對(duì)象具有同1個(gè)對(duì)象的情況(與get函數(shù)相比)。
例子以下:
auto_ptr< string > pstr_auto( new string( "Brontosaurus" ) );
auto_ptr< string > pstr_auto2( pstr_auto.get() ); //這是兩個(gè)auto_ptr具有同1個(gè)對(duì)象
auto_ptr< string > pstr_auto2( pstr_auto.release() ); //release可以首先釋放所有權(quán)
附上auto_ptr的實(shí)現(xiàn)代碼:
上一篇 VK Cup 2012 Qualification Round 1---C. Cd and pwd commands
下一篇 回?fù)鬗LAA:NVIDIA FXAA抗鋸齒性能實(shí)測(cè)、畫(huà)質(zhì)對(duì)比