標準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++可以完全避免記憶體洩露,效率只有微不足道的下降(中型以上程式最多百分之一)
c cpp中auto ptr用法分析
auto ptr example include include using namespace std int main cout p1 points to p1 n return 0 猜測一下這段程式的輸出?如果不出意外,得到的結果應該是如下這樣的。p2 points to 10 segment...
空間的作用和用法
對於乙個使用者系統預設的會建立。temp undotabs user system這幾個表空間。那請問這幾個表空間各有什麼 作用呢?當學了oracle的人都會說。temp表空間是放處理的臨時資料的,比如排序操作。undotabs表空間是資料恢復時用到。user表空間是存班實資料的。但是大家有誰能真正...
Const 的作用和用法
const型別定義 指明變數或物件的值是不能被更新,引入目的是為了取代預編譯指令 常量必須被初始化 cons的作用 1 可以定義const常量 例如 const int max 100 int array max 2 便於進行型別檢查 例如 void f const int i 編譯器就會知道i是乙...