天天看點

C++ auto_ptr智能指針的用法

文章轉載自: http://blog.csdn.net/monkey_d_meng/article/details/5901392

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

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

vector<auto_ptr<T>>m_example;

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

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

我們大多數人每天寫類似的代碼。如果f()函數隻有三行并且不會有任何意外,這麼做可能挺好的。但是如果f()從不執行delete語句,或者是由于過早的傳回,或者是由于執行函數體時抛出了異常,那麼這個被配置設定的對象就沒有被删除,進而我們産生了一個經典的記憶體洩漏。

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

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

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

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

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.如果采用方案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++可以完全避免記憶體洩露,效率隻有微不足道的下降(中型以上程式最多百分之一)。

繼續閱讀