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