智慧指標變數做函式引數的一個值得注意的地方
作者:朱金燦
先考考大家,下面一段程式,會有什麼問題:
#include <iostream> #include <string> #include "boost/smart_ptr.hpp" class MyClass { public: MyClass() { m_count = 1; m_strName = _T("xiao ming"); } void Increase() { m_count++; std::wcout<<m_strName<<_T(" increase 1 ")<<std::endl; } void ChangeName() { m_strName = _T("xiao gang"); std::wcout<<_T("The new name is ")<<m_strName<<std::endl; } std::wstring GetName() { return m_strName; } ~MyClass() { std::wcout<<_T(" Destructor")<<std::endl; } private: int m_count; std::wstring m_strName; }; void Process(boost::shared_ptr<MyClass>& ptrParam) { ptrParam->Increase(); std::wcout<<ptrParam->GetName()<<_T(" enter Procees function")<<std::endl; } void CallFunction() { MyClass* pNewInstance = new MyClass(); { boost::shared_ptr<MyClass> ptrParam(pNewInstance); Process(ptrParam); } pNewInstance->ChangeName(); } int _tmain(int argc, _TCHAR* argv[]) { CallFunction(); system("pause"); return 0; }
下午同事就遇到上面一段程式類似的問題,他不明白程式為何會在pNewInstance->ChangeName();這一句崩潰。當時我也不是很確定,就這樣分析:智慧指標變數boost::shared_ptr<MyClass>ptrParam作為一個區域性變數,當離開其作用域時,估計是執行了MyClass解構函式。
晚上回來查了下資料,比較標準的解釋是:智慧指標自動地增加和減少它指向物件的引用計數,當物件引用計數減少到0的時候自動摧毀。如果一個函式使用智慧指標作為引數,那麼不要把一個沒有被其他智慧指標引用的物件常規指標作為引數傳入到函式中。如果這樣做,那麼這個物件指標將會被摧毀掉。接下來是這個問題詳細描述:
1 常規指標pkObject指向一個動態分配的物件,其引用計數為0。
2 傳輸pkObject到一個智慧指標引數,編譯器隱式呼叫智慧指標的建構函式將pkObject轉換到一個臨時的智慧指標,並將物件的引用計數增加到1。
3 在函式呼叫的作用域,這個臨時智慧指標通過呼叫智慧指標的拷貝建構函式複製到一個區域性智慧指標中,並將物件的引用計數增加到2。
4 當函式呼叫返回的時候,區域性智慧指標被摧毀,並將物件的引用計數減少到1。
5 在呼叫完成的時候,臨時智慧指標物件也被摧毀,並將物件的引用計數減少到0,這導致物件被釋放掉。
參考文獻:
1.智慧指標
如果你覺得我的部落格對你有幫助,請在下面網址中部落格之星評選活動投我一票:
參與投票有機會獲獎:
最佳貢獻獎:通過微博分享活動就有機會獲得30元充值卡一張(每週抽選5名)
幸運獎:凡參與投票使用者就有機會獲得精美小禮品一份。(每週抽選5名)
積極參與獎:所有參與投票並符合條件的使用者均可獲得20個下載積分。