auto_ptr類實現了較為安全的指標。例如在這種情況下:
void foo()
如果在do_something()中丟擲異常,且未**獲,那麼ptr指標無法被delete,造成記憶體洩漏。
利用c++提供的auto_ptr類改寫之,則可以解決這個問題:
void foo()
那麼auto_ptr是怎麼實現的呢?開啟memory標頭檔案(這裡以devc++ 4.9.9.2版本中所帶的g++編譯器include目錄下的memory標頭檔案為例)一**竟吧~
auto_ptr類是乙個類模板,模板形參_tp,擁有乙個private的指標,即使用者想要交給其管理的指標。
其餘成員包括各種建構函式/複製建構函式/賦值操作符:
explicit auto_ptr(element_type* __p = 0);
auto_ptr(auto_ptr& __a); // 注意引數不是常規的const引用,稍候詳談
templateauto_ptr(auto_ptr<_tp1>& __a);
auto_ptr(auto_ptr_ref__ref);
~auto_ptr();
auto_ptr& operator=(auto_ptr& __a);
templateauto_ptr& operator=(auto_ptr<_tp1>& __a);
auto_ptr& operator=(auto_ptr_ref__ref);
auto_ptr對外提供的介面:
element_type& operator*() const;
element_type* operator->() const;
element_type* get() const;
element_type* release();
void reset(element_type* __p = 0);
還有兩個型別轉換操作符:
templateoperator auto_ptr_ref<_tp1>();
templateoperator auto_ptr<_tp1>()
大部分**都比較簡單易懂,只需要注意auto_ptr類實現的賦值和複製行為與通常不同,完成對目標物件的賦值/複製操作的同時,源物件會成為未繫結的auto_ptr。
比較引人關注的是那個非const引用的複製建構函式。試想有這樣的函式:
templatevoid foo(auto_ptr);
templateauto_ptrbar(void);
要實現這樣的呼叫:
foo(auto_ptr(new int (123)));
auto_ptrap = bar();
那麼傳給foo()的引數是乙個臨時物件,從bar()返回的引數也是臨時物件。傳參的時候會呼叫複製建構函式,而從bar()返回的時候會呼叫賦值操作符。兩者情況類似,讓我們看看複製建構函式中發生的事情。
由於臨時物件是右值,所以複製建構函式的引數應該是const引用。但是,如果是const引用的話,就沒辦法修改源物件持有的指標了。對了,我們還有mutable關鍵字。如果給指標加上了mutable的修飾,倒是可以修改了,可問題是,如果源物件確實是乙個const的auto_ptr怎麼辦呢?
來看看大師們的設計:將複製建構函式的引數設定為non-const引用,增加乙個新的輔助類auto_ptr_ref
其定義如下:
/**
* for example, an auto_ptr can be assigned (or constructed from)
* the result of a function which returns an auto_ptr by value.**/
templatestruct auto_ptr_ref
};
這樣的設計要實現的目標是,從乙個右值構造出auto_ptr物件。
那麼這個輔助類是怎樣工作的呢?總的來說是兩步轉換,從auto_ptr到auto_ptr_ref,再到auto_ptr。還是以複製建構函式為例。在前面對foo()函式的呼叫中,臨時物件是auto_ptr類型別,自然不會呼叫接受non-const引用引數的複製建構函式。那麼唯一可能進行的只能是從auto_ptr_ref類進行構造了。現在那個神奇的轉換操作符就起作用了:
templateoperator auto_ptr_ref<_tp1>() throw()
在轉換時,將原來的auto_ptr置成未繫結的物件,用它持有的指標構造了乙個auto_ptr_ref物件。接著再用這個auto_ptr_ref物件構造出乙個新的auto_ptr物件,把這個新物件傳給foo()函式。
為了驗證一下這個過程,修改一下memory標頭檔案中的**,在以下位置加上printf語句:
1. 上述的轉換操作符
2. 用auto_ptr_ref類的建構函式
3. auto_ptr的析構函式
4. auto_ptr_ref的析構函式(自己加上乙個析構函式定義)
然後執行這段程式:
#include #include using namespace std;
template void foo(auto_ptra)
int main()
輸出如下:
convert to auto_ptr_ref析構的三個物件中,有臨時物件、新構造出的auto_ptr物件和看不見的auto_ptr_ref物件。對於賦值操作符,也可以用相同的方法跟蹤一下執行流程。只不過它呼叫的是引數為auto_ptr_ref的賦值操作符。construct an auto_ptr from auto_ptr_ref
123destroy an auto_ptr
destroy an auto_ptr_ref
destroy an auto_ptr
這樣一來便解決了foo()和bar()函式的問題。主要根源還是在於auto_ptr類與眾不同的複製和賦值行為。
ok~就寫到這兒~累死人啊……第一篇啊……純屬菜鳥胡言,歡迎眾大師拍磚,不喜者請繞道……eof
auto ptr模板類 智慧型指標
auto ptr模板類 auto ptr模板定義了類似指標的物件,可以將new獲得 直接或間接 的位址賦給這種物件。當auto ptr物件過期時,其析構函式將使用delete來釋放記憶體。要建立auto ptr物件,必須包含標頭檔案memory。使用通常的模板句法來例項化所需型別的指標。模板中包括 ...
用auto ptr類模板幫助動態記憶體管理
動態記憶體使用最多的是在c 應用程式的 中。有過程式設計經驗的程式設計師雖然都知道new操作符的使用一定要與delete匹配,在某些場合仍然可能有記憶體溢位。當異常被擲出時,程式的正常控制流程被改變,因此導致潛在的記憶體溢位。例如,void g 可能擲出 void func int main cat...
用auto ptr類模板幫助動態記憶體管理
用auto ptr類模板幫助動態記憶體管理 趙湘寧動態記憶體使用最多的是在c 應用程式的 中。有過程式設計經驗的程式設計師雖然都知道new操作符的使用一定要與delete匹配,在某些場合仍然可能有記憶體溢位。當異常被擲出時,程式的正常控制流程被改變,因此導致潛在的記憶體溢位。例如,void g 可能...