多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > 互聯網 > 【C++智能指針 auto_ptr】

【C++智能指針 auto_ptr】

來源:程序員人生   發布時間:2014-11-18 08:23:07 閱讀次數:2670次

《More Effective C++》ITEM M9中提到了auto_ptr,說是當異常產生的時候,怎樣釋放為對象分配的堆內存,避免重復編寫內存釋放語句。

PS:這里書里面提到函數退出問題,函數退出會清算棧內存,不論是怎樣正常退出還是異常退出(唯一1種例外就是當你調用 longjmp 時。Longjmp 的這個缺點是 C++率先支持異常處理的主要緣由)。建立在此基礎上我們才把對指針的刪除操作封裝到1個棧對象里面。這樣函數退出(異?;蚴钦#┚蜁{用對象的析構函數,到達我們自動清算所封裝指針指向的內存的目的。

作為新手,不是很理解,記下來,學習學習。

PS:C++11已不提倡用auto_ptr了,請看鏈接: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.


以下內容copy自:http://blog.sina.com.cn/s/blog_7708265a01010lyv.html

1. auto_ptr是甚么?

auto_ptr 是C++標準庫提供的類模板,auto_ptr對象通過初始化指向由new創建的動態內存,它是這塊內存的具有者,1塊內存不能同時被分給兩個具有者。當auto_ptr對象生命周期結束時,其析構函數會將auto_ptr對象具有的動態內存自動釋放。即便產生異常,通過異常的棧展開進程也能將動態內存釋放。auto_ptr不支持new 數組。

 

2. auto_ptr需要包括的頭文件?

#include <memory>

 

3. 初始化auto_ptr對象的方法?

1) 構造函數

1] 將已存在的指向動態內存的普通指針作為參數來構造

int* p = new int(33);

auto_ptr<int> api(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

由于1塊動態內存智能由1個智能指針獨享,所以在拷貝構造或賦值時都會產生具有權轉移的進程。在此拷貝構造進程中,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對象具有同1個對象(1塊內存)

由于auto_ptr的所有權獨有,所以下面的代碼會造成混亂。

int* p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);

由于ap1與ap2都認為指針p是歸它管的,在析構時都試圖刪除p, 兩次刪除同1個對象的行動在C++標準中是未定義的。所以我們必須避免這樣使用auto_ptr。

 

6. 警惕智能指針作為參數!

1) 按值傳遞時,函數調用進程中在函數的作用域中會產生1個局部對象來接收傳入的auto_ptr(拷貝構造),這樣,傳入的實參auto_ptr就失去了其對原對象的所有權,而該對象會在函數退出時被局部auto_ptr刪除。以下例:

void f(auto_ptr<int> ap)

{cout<<*ap;}
auto_ptr<int> ap1(new int(0));
f(ap1);
cout<<*ap1; //毛病,經過f(ap1)函數調用,ap1已不再具有任何對象了。

2) 援用或指針時,不會存在上面的拷貝進程。但我們其實不知道在函數中對傳入的auto_ptr做了甚么,如果當中某些操作使其失去了對對象的所有權,那末這還是可能會致使致命的履行期毛病。

結論:const reference是智能指針作為參數傳遞的底線。

 

7. auto_ptr不能初始化為指向非動態內存

緣由很簡單,delete 表達式會被利用在不是動態分配的指針上這將致使未定義的程序行動。

 

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

1) get()

返回auto_ptr指向的那個對象的內存地址。以下例:

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所在的那塊內存的地址。第2行是ap1這個類對象本身所在內存的地址。

2) reset()

重新設置auto_ptr指向的對象。類似于賦值操作,但賦值操作不允許將1個普通指針指直接賦給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對象具有同1個對象的情況(與get函數相比)。

例子以下:

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

auto_ptr< string > pstr_auto2( pstr_auto.get() ); //這是兩個auto_ptr具有同1個對象

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

附上auto_ptr的實現代碼:

namespace std { template<class T> class auto_ptr { private: T* ap; public: // constructor & destructor ----------------------------------- (1) explicit auto_ptr (T* ptr = 0) throw() : ap(ptr){} ~auto_ptr() throw() { delete ap; } // Copy & assignment --------------------------------------------(2) auto_ptr (auto_ptr& rhs) throw() :ap(rhs.release()) {} template<class Y> auto_ptr (auto_ptr<Y>& rhs) throw() : ap(rhs.release()) { } auto_ptr& operator= (auto_ptr& rhs) throw() { reset(rhs.release()); return *this; } template<class Y> auto_ptr& operator= (auto_ptr<Y>& rhs) throw() { reset(rhs.release()); return *this; } // Dereference----------------------------------------------------(3) T& operator*() const throw() { return *ap; } T* operator->() const throw() { return ap; } // Helper functions------------------------------------------------(4) // value http://www.vxbq.cn/access/ T* get() const throw() { return ap; } // release ownership T* release() throw() { T* tmp(ap); ap = 0; return tmp; } // reset value void reset (T* ptr=0) throw() { if (ap != ptr) { delete ap; ap = ptr; } } // Special conversions-----------------------------------------------(5) template<class Y> struct auto_ptr_ref { Y* yp; auto_ptr_ref (Y* rhs) : yp(rhs) {} }; auto_ptr(auto_ptr_ref<T> rhs) throw() : ap(rhs.yp) { } auto_ptr& operator= (auto_ptr_ref<T> rhs) throw() { reset(rhs.yp); return *this; } template<class Y> operator auto_ptr_ref<Y>() throw() { return auto_ptr_ref<Y>(release()); } template<class Y> operator auto_ptr<Y>() throw() { return auto_ptr<Y>(release()); } }; }


生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲欧美不卡中文字幕 | 亚洲天堂成人网 | 久久久久久久性 | 国产亚洲欧美一区 | 日韩欧美高清 | 青青自拍视频一区二区三区 | 波多野结衣手机视频一区 | 亚洲精品国产第一区二区图片 | 成成人看片在线 | 色人阁在线 | 欧美日本在线播放 | 亚洲精品国产第一区二区三区 | 2022国产成人精彩在线视频 | 精品一区二区三区中文 | 精品福利网 | 亚洲伦理一二三四 | 成人动漫中文字幕 | 好大好湿好硬顶到了好爽(双性) | 麻豆国产96在线 | 日韩 | 久久免费大片 | 网站视频大片www | 亚洲欧美另类色妞网站 | 日本欧美小视频 | 国产不卡一区二区三区免费视 | 波多野结衣久久精品免费播放 | 国产综合成人久久大片91 | 日韩欧美亚洲国产一区二区三区 | 校园春色另类 | 日本特黄特色免费大片 | 亚洲伊人99综合网 | 男人把大ji巴放进男人免费视频 | 国产情精品嫩草影院88av | 加勒比一本大道香蕉在线视频 | 亚洲国产精品尤物yw在线观看 | 国产成人 免费观看 | 最近中文字幕在线 | 中文字幕乱码在线 | 国产在线原创剧情麻豆 | 欧美精品另类 | 免费a网站 | 日韩欧美亚洲另类 |