AUTO PTR使用總結

2021-06-16 09:00:59 字數 2894 閱讀 5789

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

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

auto_ptr所做的事情,就是動態分配物件以及當物件不再需要時自動執行清理。這裡是乙個簡單的**示例,沒有使用auto_ptr所以不安全:    

// 示例 1(a): 原始**     //    

void f()    

我們大多數人每天寫類似的**。如果f()函式只有三行並且不會有任何意外,這麼做可能挺好的。但是如果f()從不執行delete語句,或者是由於過早的返回,或者是由於執行函式體時丟擲了異常,那麼這個被分配的物件就沒有被刪除,從而我們產生了乙個經典的記憶體洩漏。

能讓示例1(a)安全的簡單辦法是把指標封裝在乙個「智慧型的」類似於指標的物件裡,這個物件擁有這個指標並且能在析構時自動刪除這個指標所指的物件。因為這個智慧型指標可以簡單的當成乙個自動的物件(這就是說,它出了作用域時會自動毀滅),所以很自然的把它稱之為「智慧型」指標:

// 示例 1(b): 安全**, 使用了auto_ptr     //    

void f()     // 酷: 當pt出了作用域時析構函式被呼叫,       // 從而物件被自動刪除

現在**不會洩漏t型別的物件,不管這個函式是正常退出還是丟擲了異常,因為pt的析構函式總是會在出棧時被呼叫。清理會自動進行。

最後,使用乙個auto_ptr就像使用乙個內建的指標一樣容易,而且如果想要「撤銷」資源,重新採用手動的所有權,我們只要呼叫release():

// 示例 2: 使用乙個 auto_ptr     //    

void g()     // pt2不再擁有任何指標,所以不要       // 試圖刪除它...ok,不要重複刪除

最後,我們可以使用auto_ptr的reset()函式來重置auto_ptr使之擁有另乙個物件。如果這個auto_ptr已經擁有了乙個物件,那麼,它會先刪除已經擁有的物件,因此呼叫reset()就如同銷毀這個auto_ptr,然後新建乙個並擁有乙個新物件:

// 示例 3: 使用reset()     //    

void h()     // 最後,pt出了作用域,       // 第二個t也被刪除了

auto_ptr

用法:

1.需要包含標頭檔案

2.constructor

:explicit auto_ptr(x* p = 0) throw(); 將指標p交給auto_ptr物件託管

3.copy constructor: auto_ptr(const auto_ptr&) throw(); templateauto_ptr(const auto_ptr& a) throw(); 

指標的託管權會發生轉移

4.destructor: ~auto_ptr(); 

釋放指標p指向的空間

5.提供了兩個成員函式 x* get() const throw();//返回儲存的指標,物件中仍保留指標 x* release() const throw();//返回儲存的指標,物件中不保留指標

auto_ptr

實現關鍵點 1.利用特點」棧上物件在離開作用範圍時會自動析構」

2.對於動態分配的記憶體,其作用範圍是程式設計師手動控制的,這給程式設計師帶來了方便但也不可避免疏忽造成的記憶體洩漏,畢竟只有編譯器是最可靠的。

3.auto_ptr

通過在棧上構建乙個物件a,物件a中wrap了動態分配記憶體的指標p,所有對指標p的操作都轉為對物件a的操作。而在a的析構函式中會自動釋放p的空間,而該析構函式是編譯器自動呼叫的,無需程式設計師操心。

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

#include

#include

using namespace std;

class tc

;void foo(bool isthrow)

catch(const char* e)

//delete ptc;           //

方法1

}int main()

catch(...)

system("pause");}1.

如果採用方案1,那麼必須考慮到函式在因throw異常的時候釋放所分配的記憶體。 這樣造成的結果是在每個分支處都要很小心的手動 delete ptc;

2.如果採用方案2,那就無需操心何時釋放記憶體,不管foo()因何原因退出, 棧上物件ptc的析構函式都將呼叫,因此託管在之中的指標所指的記憶體必然安全釋放。

至此,智慧型指標的優點已經很明了了。

但是要注意使用中的乙個陷阱,那就是指標的託管權是會轉移的。 例如在上例中,如果 auto_ptrptc(new tc);   auto_ptrptc1=ptc; 那麼,ptc1將擁有該指標,而ptc沒有了,如果再用ptc去引用,必然導致記憶體錯誤。

要避免這個問題,可以考慮使用採用了引用計數的智慧型指標,例如boost::shared_ptr等

auto_ptr不會降低程式的效率,但auto_ptr不適用於陣列,auto_ptr根本不可以大規模使用。 shared_ptr也要配合weaked_ptr,否則會很容易觸發迴圈引用而永遠無法**記憶體。理論上,合理使用容器加智慧型指標,c++可以完全避免記憶體洩露,效率只有微不足道的下降(中型以上程式最多百分之一)

**:

auto ptr使用總結

1 auto ptr的意義 auto ptr是一種智慧型指標,當系統異常退出的時候避免資源洩漏 記憶體 其他的資源還對應其他的智慧型指標。2 auto ptr的使用 std auto ptrtest new int 1 test將是乙個auto ptr的物件,使用乙個int指標進行初始化。test可...

auto ptr使用總結

1 auto ptr的意義 auto ptr是一種智慧型指標,當系統異常退出的時候避免資源洩漏 記憶體 其他的資源還對應其他的智慧型指標。2 auto ptr的使用 std auto ptrtest new int 1 test將是乙個auto ptr的物件,使用乙個int指標進行初始化。test可...

經驗總結 auto ptr使用小結

注意點 1 不能用auto ptr管理陣列指標 析構時用delete p方式釋放 2 缺少引用計數機制。賦值和拷貝時,原始的auto ptr被釋放 pointee變為null 3 一塊記憶體不能同時被兩個auto ptr管理,否則會出現記憶體重複釋放的問題。實現要點 1 過載訪問符號 和 templ...