在c++程序中,內存管理中經常隱藏著很深的bug。
雖然我們一般可以采用vector,string,map等容器自動管理內存,
但涉及多態,繼承的時候也不可避免的要手動管理,c++標準庫中提供的auto_ptr能一定程度上幫助我們。
auto_ptr用法:
1.需要包含頭文件
2.Constructor:explicit auto_ptr(X* p = 0) throw();
將指針p交給auto_ptr對象托管
3.Copy constructor:
auto_ptr(const auto_ptr&) throw();
template
指針的托管權會發生轉移
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的空間,而該析構函數是編譯器自動調用的,無需程序員操心。
多說無益,看一個最實用的例子:



















































分析:
1.如果采用方案1,那么必須考慮到函數在因throw異常的時候釋放所分配的內存。
這樣造成的結果是在每個分支處都要很小心的手動 delete pTC;
2.如果采用方案2,那就無需操心何時釋放內存,不管foo()因何原因退出,
棧上對象pTC的析構函數都將調用,因此托管在之中的指針所指的內存必然安全釋放。
注意:
至此,智能指針的優點已經很明了了。
但是要注意使用中的一個陷阱,那就是指針的托管權是會轉移的。
例如在上例中,如果
auto_ptr
auto_ptr
那么,pTC1將擁有該指針,而pTC沒有了,如果再用pTC去引用,必然導致內存錯誤。
要避免這個問題,可以考慮使用采用了引用計數的智能指針,例如boost::shared_ptr等
個人觀點
1.
vc++庫中的智能指針auto_ptr本不像都像前面介紹的那樣
auto_ptr
auto_ptr
其中pTC指針并沒有被托管,其地址還是指向new TC 的。但是并沒有出現同一個指針釋放兩次的問題。
2.VC中的 auto_ptr是一個對象,和內置指針是不一樣的,它沒有支持測試智能指針NULL的功能。
auto_ptr<TestC> p;
if(p == NULL); 并沒有辦法通過編譯。
3.并不支持將智能指針轉化為內置指針,如:
void print(TestC* p)
//...
}
auto_ptr<TestC> p(new TestC);
print(p);沒有辦法通過編譯
解決的辦法是重載operator T*();
4.內置指針在c++中一個重要的作用是用來實現多態,但是vc++智能指針并不支持.
實現的方法是
template<class T>
template <class U>
MyAuto_ptr(MyAuto_ptr<U>& rhs);
可以參考:《More Effective c++ 》條款28 P158