如你所知,auto_ptr是智能指標。其源碼可以到memory.h中看到,下面的代碼為其源碼的一部分,展示了智能指標到底是如何工作的。
先說說智能指標的特點:
1. 持有一個指標。
2. 表現得像一個指標,能夠像指標那樣操作->, *等等。
3. 智能指標不需要手動釋放。
#pragma once//////////////////////////////////////////////////////////////////////////template<class element_type>class auto_ptr{public: // Q: 為什麼這裡要使用explicit?A: 為了避免自動轉型帶來的未知的行為。 // 構造一個智能指標,需要指定這個指標的地址。 // auto_ptr在持有這個指標的地址之後,外界不需要在對這個地址進行析構, // 否則會出錯,因為這樣會造成一個指標唄析構兩次。 explicit auto_ptr(element_type *ptr = 0) : m_pInnerPtr(ptr) { // construct from object pointer } // 拷貝建構函式。被拷貝的對象將不再持有這個指標。 // 這種情況應用於將auto_ptr像普通對象那樣使用傳值方式作為函數調用的參數。 // 此時會發生拷貝構造的調用。如果實參繼續持有原始指標,那麼實參在析構時會導致這個指標被多次析構。 // 調用拷貝構造之後,指標的控制權轉移到當前對象,right對象不再享有對原始指標的控制權。 auto_ptr(auto_ptr<element_type>& right) : m_pInnerPtr(right.release()) { // construct by assuming pointer from _Right auto_ptr } // 賦值操作符。複製操作與拷貝構造看起來一樣,但是他們的區別就是調用賦值操作符的時候, // 已經存在了一個auto_ptr的對象。所以此時要去reset一下老的指標。 // 同時將right對象中的指標控制權轉移到當前對象中來。 auto_ptr<element_type>& operator=(auto_ptr<element_type>& right) { reset(right.release()); return (*this); } // 解構函式,由於auto_ptr以對象的形式展示給程式員, // auto_ptr的解構函式會在函數調用退出時自動調用,此時析構被持有的原始指標, // 這樣就不需要程式員手動去析構這個指標了。 ~auto_ptr() { // destroy the object if (m_pInnerPtr != 0) delete m_pInnerPtr; } // 解引用操作符,重載的目的是為了是auto_ptr這個對象表現的像一個真實的指標。 element_type& operator*() const { // return designated value return (*get()); } // 指標叫用作業符,重載的目的是為了是auto_ptr這個對象表現的像一個真實的指標。 element_type *operator->() const { // return pointer to class object return (get()); } // 取出原始指標,為擷取該指標。但是使用者在擷取這個指標之後, // 不可以對其進行析構,因為auto_ptr對象會在解構函式總析構原始指標。 element_type *get() const { // return wrapped pointer return (m_pInnerPtr); } // release函數的目的是交出原始指標,轉移控制權。 // 調用了release之後,auto_ptr將不再控制這個指標。 element_type *release() { // return wrapped pointer and give up ownership element_type *pTmp = m_pInnerPtr; m_pInnerPtr = 0; return (pTmp); } // reset函數的木器是重新設定auto_ptr所控制的對象。 // 如果auto_ptr之前已經控制了一個指標,那麼這個指標將會被銷毀, // 最終,auto_ptr對象將控制入參所傳遞的指標。 // reset會在operator=函數中調用,其目的就是要重新設定auto_ptr對象所控制的指標, // 同時確保沒有記憶體泄露 void reset(element_type* ptr = 0) { // destroy designated object and store new pointer if (ptr != m_pInnerPtr && m_pInnerPtr != 0) delete m_pInnerPtr; m_pInnerPtr = ptr; }private: element_type *m_pInnerPtr; // the wrapped object pointer};
寫這篇文章的目的是在參加某IT公司面試的時候對方要求我設計一個auto_ptr的源碼,雖然平時使用過boost::smart_ptr的源碼,但是讓我寫,我一時半會還真想不了那麼完全,最終fail了!
在看了auto_ptr的源碼之後,才明白了原來是這麼一回事,與大家分享。