閒得慌 看auto ptr模板類原始碼玩

2021-08-24 21:43:10 字數 3126 閱讀 4726

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

construct an auto_ptr from auto_ptr_ref

123destroy an auto_ptr

destroy an auto_ptr_ref

destroy an auto_ptr

析構的三個物件中,有臨時物件、新構造出的auto_ptr物件和看不見的auto_ptr_ref物件。對於賦值操作符,也可以用相同的方法跟蹤一下執行流程。只不過它呼叫的是引數為auto_ptr_ref的賦值操作符。

這樣一來便解決了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 可能...