一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++中auto_ptr智能指針的用法詳解

C++中auto_ptr智能指針的用法詳解

2021-04-09 13:50MONKEY_D_MENG C/C++

這篇文章主要介紹了C++中auto_ptr智能指針的用法詳解的相關資料,需要的朋友可以參考下

智能指針(auto_ptr) 這個名字聽起來很酷是不是?其實auto_ptr 只是C++標準庫提供的一個類模板,它與傳統的new/delete控制內存相比有一定優勢,但也有其局限。本文總結的8個問題足以涵蓋auto_ptr的大部分內容。

auto_ptr是什么?

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

C++中指針申請和釋放內存通常采用的方式是new和delete。然而標準C++中還有一個強大的模版類就是auto_ptr,它可以在你不用的時候自動幫你釋放內存。下面簡單說一下用法。

?
1
<textarea cols="50" rows="15" name="code" class="cpp">

用法一: std::auto_ptr&lt;MyClass&gt;m_example(new MyClass());

用法二: std::auto_ptr&lt;MyClass&gt;m_example; m_example.reset(new MyClass());

用法三(指針的賦值操作): std::auto_ptr&lt;MyClass&gt;m_example1(new MyClass());

std::auto_ptr&lt;MyClass&gt;m_example2(new MyClass()); m_example2=m_example1;</textarea>

則C++會把m_example所指向的內存回收,使m_example1 的值為NULL,所以在C++中,應絕對避免把auto_ptr放到容器中。即應避免下列代碼:

vector<auto_ptr<MyClass>>m_example;

當用算法對容器操作的時候,你很難避免STL內部對容器中的元素實現賦值傳遞,這樣便會使容器中多個元素被置位NULL,而這不是我們想看到的。

雖然,標準auto_ptr智能指針機制很多人都知道,但很少使用它。這真是個遺憾,因為auto_ptr優雅地解決了C++設計和編碼中常見的問題,正確地使用它可以生成健壯的代碼。本文闡述了如何正確運用auto_ptr來讓你的代碼更加安全——以及如何避免對auto_ptr危險但常見的誤用,這些誤用會引發間斷性發作、難以診斷的bug。

為什么稱它為“自動”指針?auto_ptr只是眾多可能的智能指針之一。許多商業庫提供了更復雜的智能指針,用途廣泛而令人驚異,從管理引用的數量到提供先進的代理服務。可以把標準C++ auto_ptr看作智能指針的Ford Escort(elmar注:可能指福特的一種適合家居的車型):一個簡易、通用的智能指針,它不包含所有的小技巧,不像專用的或高性能的智能指針那么奢華,但是它可以很好的完成許多普遍的工作,它很適合日常性的使用。

auto_ptr所做的事情,就是動態分配對象以及當對象不再需要時自動執行清理。這里是一個簡單的代碼示例,沒有使用auto_ptr所以不安全:

?
1
<textarea cols="50" rows="15" name="code" class="cpp">// 示例1(a):原始代碼 void f() { T* pt( new T ); /*...更多的代碼...*/ delete pt; }</textarea>

我們大多數人每天寫類似的代碼。如果f()函數只有三行并且不會有任何意外,這么做可能挺好的。但是如果f()從不執行delete語句,或者是由于過早的返回,或者是由于執行函數體時拋出了異常,那么這個被分配的對象就沒有被刪除,從而我們產生了一個經典的內存泄漏。

能讓示例1(a)安全的簡單辦法是把指針封裝在一個“智能的”類似于指針的對象里,這個對象擁有這個指針并且能在析構時自動刪除這個指針所指的對象。因為這個智能指針可以簡單的當成一個自動的對象(這就是說,它出了作用域時會自動毀滅),所以很自然的把它稱之為“智能”指針:

?
1
2
<textarea cols="50" rows="15" name="code" class="cpp">//
示例1(b):安全代碼,使用了auto_ptr void f() { auto_ptr&lt;T&gt; pt( new T ); /*...更多的代碼...*/ } // 酷:當pt出了作用域時析構函數被調用,從而對象被自動刪除</textarea>

現在代碼不會泄漏T類型的對象,不管這個函數是正常退出還是拋出了異常,因為pt的析構函數總是會在出棧時被調用,清理會自動進行。

最后,使用一個auto_ptr就像使用一個內建的指針一樣容易,而且如果想要“撤銷”資源,重新采用手動的所有權,我們只要調用release()。

?
1
<textarea cols="50" rows="15" name="code" class="cpp">// 示例2:使用一個auto_ptr void g() { // 現在,我們有了一個分配好的對象 T* pt1 = new T; // 將所有權傳給了一個auto_ptr對象 auto_ptr&lt;T&gt; pt2(pt1); // 使用auto_ptr就像我們以前使用簡單指針一樣, *pt2 = 12; // 就像*pt1 = 12 pt2-&gt;SomeFunc(); // 就像pt1-&gt;SomeFunc(); // 用get()來獲得指針的值 assert( pt1 == pt2.get() ); // 用release()來撤銷所有權 T* pt3 = pt2.release(); // 自己刪除這個對象,因為現在沒有任何auto_ptr擁有這個對象 delete pt3; } // pt2不再擁有任何指針,所以不要試圖刪除它...OK,不要重復刪除 </textarea>

最后,我們可以使用auto_ptr的reset()函數來重置auto_ptr使之擁有另一個對象。如果這個auto_ptr已經擁有了一個對象,那么,它會先刪除已經擁有的對象,因此調用reset()就如同銷毀這個auto_ptr,然后新建一個并擁有一個新對象:

 

?
1
2
<textarea cols="50" rows="15" name="code" class="cpp">//
示例 3:使用reset() void h() { auto_ptr&lt;T&gt; pt( new T(1) ); pt.reset( new T(2) ); // 刪除由"new T(1)"分配出來的第一個T } // 最后pt出了作用域,第二個T也被刪除了</textarea>

auto_ptr用法:

1. 需要包含頭文件<memory>。

2. Constructor:explicit auto_ptr(X* p = 0) throw(); 將指針p交給auto_ptr對象托管。

3. Copy constructor:auto_ptr(const auto_ptr&) throw(); template<class Y> auto_ptr(const auto_ptr<Y>& a) throw(); 指針的托管權會發生轉移。

4. Destructor: ~auto_ptr(); 釋放指針p指向的空間。

5. 提供了兩個成員函數 X* get() const throw(); //返回保存的指針

6. 對象中仍保留指針 X* release() const throw(); //返回保存的指針,對象中不保留指針

auto_ptr實現關鍵點:

1. 利用特點“棧上對象在離開作用范圍時會自動析構”。

2. 對于動態分配的內存,其作用范圍是程序員手動控制的,這給程序員帶來了方便但也不可避免疏忽造成的內存泄漏,畢竟只有編譯器是最可靠的。
3. auto_ptr通過在棧上構建一個對象a,對象a中wrap了動態分配內存的指針p,所有對指針p的操作都轉為對對象a的操作。而在a的析構函數中會自動釋放p的空間,而該析構函數是編譯器自動調用的,無需程序員操心。

多說無益,看一個最實用的例子:

?
1
2
3
<textarea cols="50" rows="15" name="code" class="cpp">#include &lt;iostream&gt; #include &lt;memory&gt; using namespace std; class TC { public: TC(){cout&lt;&lt;"TC()"&lt;&lt;endl;} ~TC(){cout&lt;&lt;"~TC()"&lt;&lt;endl;} }; void foo(bool isThrow) { auto_ptr&lt;TC&gt; pTC(new TC);
// 方法2 //TC *pTC = new TC;
// 方法1 try { if(isThrow) throw "haha"; } catch(const char* e) { //delete pTC; // 方法1 throw; } //delete pTC; // 方法1 } int main() { try { foo(true); } catch(...) { cout&lt;&lt;"caught"&lt;&lt;endl; } system("pause"); }</textarea>

1. 如果采用方案1,那么必須考慮到函數在因throw異常的時候釋放所分配的內存,這樣造成的結果是在每個分支處都要很小心的手動 delete pTC;。

2. 如果采用方案2,那就無需操心何時釋放內存,不管foo()因何原因退出, 棧上對象pTC的析構函數都將調用,因此托管在之中的指針所指的內存必然安全釋放。
至此,智能指針的優點已經很明了了。

但是要注意使用中的一個陷阱,那就是指針的托管權是會轉移的。 例如在上例中,如果 auto_ptr<TC> pTC(new TC); auto_ptr<TC> pTC1=pTC; 那么,pTC1將擁有該指針,而pTC沒有了,如果再用pTC去引用,必然導致內存錯誤。

要避免這個問題,可以考慮使用采用了引用計數的智能指針,例如boost::shared_ptr等。auto_ptr不會降低程序的效率,但auto_ptr不適用于數組,auto_ptr根本不可以大規模使用。 shared_ptr也要配合weaked_ptr,否則會很容易觸發循環引用而永遠無法回收內存。 理論上,合理使用容器加智能指針,C++可以完全避免內存泄露,效率只有微不足道的下降(中型以上程序最多百分之一)。

以上所述是小編給大家介紹的C++中auto_ptr智能指針的用法詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!

原文鏈接:http://blog.csdn.net/monkey_d_meng/article/details/5901392

延伸 · 閱讀

精彩推薦
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
主站蜘蛛池模板: 门卫老张和女警花小说 | 成人青青草| 西西人体大胆77777视频 | www亚洲精品 | 亚洲国产成人久久综合区 | 午夜精品久久久久久久99 | 亚洲 欧美 日本 国产 高清 | 亚洲精品免费在线观看 | 99热在线只有精品 | 久久伊人影视 | 国产成人精品综合在线观看 | 2019天天干天天操 | 国产精品天天看特色大片不卡 | 久久国产综合精品欧美 | 狠狠干2016| 沉香如屑西瓜视频免费观看完整版 | 窝窝午夜理伦影院 | 美女脱了内裤打开腿让人羞羞软件 | 午夜大片在线观看 | 男人的天堂欧美 | 日本卡一卡2卡3卡4精品卡无人区 | 四虎影院免费视频 | 国产一级黄色网 | 满溢游泳池免费土豪全集下拉版 | 给我一个黄色网址 | 日本大尺度激情做爰叫床 | 天天色资料 | 小SAO货叫大声点妓女 | 日本一区二区视频在线观看 | 欧美精品一二三区 | 色综合久久日韩国产 | 精品国产精品人妻久久无码五月天 | 911爱豆传媒国产 | 成人免费体验区福利云点播 | 午夜DY888国产精品影院 | 青青操在线 | 亚洲国产成人精品激情 | 日本护士厕所xxx | 99热精品国产麻豆 | 国产偷啪 | 91色视 |