在c++程序中,內(nèi)存管理中經(jīng)常隱藏著很深的bug。 雖然我們一般可以采用vector,string,map等容器自動管理內(nèi)存,但涉及多態(tài),繼承的時候也不可避免的要手動管理,c++標(biāo)準(zhǔn)庫中提供的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 auto_ptr(const auto_ptr& a) throw();指針的托管權(quán)會發(fā)生轉(zhuǎn)移4.Destructor: ~auto_ptr();釋放指針p指向的空間5.提供了兩個成員函數(shù)X* get() const throw();//返回保存的指針,對象中仍保留指針X* release() const throw();//返回保存的指針,對象中不保留指針
auto_ptr實現(xiàn)關(guān)鍵點1.利用特點”棧上對象在離開作用范圍時會自動析構(gòu)”2.對于動態(tài)分配的內(nèi)存,其作用范圍是程序員手動控制的,這給程序員帶來了方便但也不可避免疏忽造成的內(nèi)存泄漏,畢竟只有編譯器是最可靠的。3.auto_ptr通過在棧上構(gòu)建一個對象a,對象a中wrap了動態(tài)分配內(nèi)存的指針p,所有對指針p的操作都轉(zhuǎn)為對對象a的操作。而在a的析構(gòu)函數(shù)中會自動釋放p的空間,而該析構(gòu)函數(shù)是編譯器自動調(diào)用的,無需程序員操心。
多說無益,看一個最實用的例子:
分析:1.如果采用方案1,那么必須考慮到函數(shù)在因throw異常的時候釋放所分配的內(nèi)存。這樣造成的結(jié)果是在每個分支處都要很小心的手動 delete pTC;2.如果采用方案2,那就無需操心何時釋放內(nèi)存,不管foo()因何原因退出,棧上對象pTC的析構(gòu)函數(shù)都將調(diào)用,因此托管在之中的指針?biāo)傅膬?nèi)存必然安全釋放。注意:
至此,智能指針的優(yōu)點已經(jīng)很明了了。但是要注意使用中的一個陷阱,那就是指針的托管權(quán)是會轉(zhuǎn)移的。例如在上例中,如果auto_ptr pTC(new TC);auto_ptr pTC1=pTC;那么,pTC1將擁有該指針,而pTC沒有了,如果再用pTC去引用,必然導(dǎo)致內(nèi)存錯誤。要避免這個問題,可以考慮使用采用了引用計數(shù)的智能指針,例如boost::shared_ptr等個人觀點1.vc++庫中的智能指針auto_ptr本不像都像前面介紹的那樣auto_ptr pTC(new TC);auto_ptr pTC1=pTC;其中pTC指針并沒有被托管,其地址還是指向new TC 的。但是并沒有出現(xiàn)同一個指針釋放兩次的問題。2.VC中的 auto_ptr是一個對象,和內(nèi)置指針是不一樣的,它沒有支持測試智能指針NULL的功能。auto_ptr<TestC> p;if(p == NULL); 并沒有辦法通過編譯。3.并不支持將智能指針轉(zhuǎn)化為內(nèi)置指針,如:void print(TestC* p)