使用TR1的智能指针
作為C++程序員,在沒(méi)有智能指針,手動(dòng)管理內(nèi)存的蠻荒歲月里,可以說(shuō)是暗無(wú)天日,痛苦異常。直到上帝說(shuō),還是要有光,于是智能指針進(jìn)了標(biāo)準(zhǔn)。C++碼農(nóng)的日子總算好起來(lái)了。
雖然一直鄙視著沒(méi)有顯式指針的語(yǔ)言,但是對(duì)其自動(dòng)垃圾回收機(jī)制還是翹首以盼的,TR1的智能指針總算可以拿來(lái)慰藉下了。
要使用VS2008 SP1的智能指針,我們需要加入頭文件memory.h(linux 下是 tr1\memory.h),
智能指針主要是 auto_ptr, shared_ptr, weak_ptr, unique_ptr ;其中模板auto_ptr是C++98提供的解決方案,C+11已將其摒棄。然而,雖然auto_ptr被摒棄,但它已使用了好多年.因?yàn)閍uto_ptr潛在的內(nèi)存奔潰問(wèn)題,所以不推薦使用它,本文也不準(zhǔn)備討論該指針.另外unique_ptr在Tr1中還未引入.
Show me The Code
namespace tr1SharedPoint { class Ap { public:Ap(){std::cout << "Ap Construct"<<std::endl;};~Ap(){std::cout << "Ap Destruct"<<std::endl;};void pointerOutput(){std::cout << "Use smart pointer to use me "<<std::endl;} }; typedef std::tr1::shared_ptr<Ap> spAp; }測(cè)試代碼
tr1SharedPoint::Ap *ap = new tr1SharedPoint::Ap; ap->pointerOutput();執(zhí)行結(jié)果:
Ap Construct Use smart pointer to use me可見(jiàn),這里沒(méi)有調(diào)用析構(gòu)函數(shù),內(nèi)存泄漏就此發(fā)生了,需要在測(cè)試代碼中 加入 delete ap補(bǔ)救之,也就是我們以前經(jīng)常做的事情。
- shared_ptr基本使用
修改測(cè)試代碼:
tr1SharedPoint::spAp ap(new tr1SharedPoint::Ap); ap->pointerOutput();執(zhí)行結(jié)果:
Ap Construct Use smart pointer to use me Ap Destruct如此,一個(gè)指針的完美閉環(huán)就此產(chǎn)生了。我們不需要再手動(dòng)添加delete語(yǔ)句,等到share_prt的作用域消失時(shí),將自動(dòng)調(diào)用Ap類的析構(gòu)函數(shù)。很多局部鎖的類也是如此構(gòu)造的;
- weak_ptr基本使用
上面的代碼 無(wú)法使用weak_ptr直接替換shared_ptr,因?yàn)閣eak_ptr是一種不控制指向?qū)ο笊嫫诘闹悄苤羔?它指向一個(gè)shared_ptr管理的對(duì)象.調(diào)用lock()將返回一個(gè)shared_ptr對(duì)象,通過(guò)判斷該值可以知道weak_ptr指向的內(nèi)存是否已經(jīng)被釋放.
測(cè)試代碼如下:
tr1SharedPoint::wpAp wp; {tr1SharedPoint::spAp ap(new tr1SharedPoint::Ap);wp = ap;if(wp.lock()){std::cout << "ap not Destruct" <<std::endl;std::cout <<"refence Num " <<wp.use_count() <<std::endl;}ap->pointerOutput(); }if(!wp.lock()){std::cout << "ap IS Destruct" <<std::endl;std::cout <<"refence Num " <<wp.use_count() <<std::endl;}運(yùn)行結(jié)果
Ap Construct ap not Destruct refence Num 1 Use smart pointer to use me Ap Destruct ap IS Destruct refence Num 0以上可知,weak_ptr能通過(guò)lock()判斷其管理的shared_ptr是否釋放,通過(guò)use_count()知道shared_ptr被引用的次數(shù)
可是 只了解這么一點(diǎn)知識(shí)就可以了么?
答案是,可能是的。如果你只是個(gè)總忘記調(diào)用delete的C++程序員。有興趣的可以繼續(xù)閱讀.
知道更多
按上面的智能指針的用法,我們使用了new運(yùn)算符,卻沒(méi)有顯式的delete,造成了代碼的不對(duì)稱感,為了消除這種不對(duì)稱,而又使用智能指針,我們最合適的方案是使用make_shared函數(shù)來(lái)聲明內(nèi)存的分配,可惜的是,TR1中并沒(méi)有包含這個(gè)函數(shù),限于本文的標(biāo)準(zhǔn)范圍,我們只能通過(guò)boost等三方庫(kù)來(lái)支持,可是如果使用了boost的內(nèi)存語(yǔ)法,又沒(méi)有必要使用TR1了.一個(gè)可能的方案就是把new給封裝起來(lái),眼不見(jiàn)為靜.后期介紹C++11后,我們?cè)賮?lái)研究現(xiàn)在C++是如何完整的處理動(dòng)態(tài)內(nèi)存問(wèn)題的.其實(shí),這個(gè)問(wèn)題在C++ Primer中有很詳細(xì)的介紹.
堅(jiān)持只使用智能指針,就可以避免 1.忘記delete內(nèi)存 2.使用已經(jīng)釋放掉的對(duì)象 3.同一塊內(nèi)存釋放兩次 這3類問(wèn)題,對(duì)于一塊內(nèi)存,只有在沒(méi)有任何智能指針指向它的情況下,智能指針才會(huì)自動(dòng)釋放它.
- 在可能循環(huán)引用的類中,使用weak_ptr
weak_ptr更常用的用法是解決shared_ptr相互引用時(shí)的死鎖問(wèn)題,如果說(shuō)兩個(gè)shared_ptr相互引用,那么這兩個(gè)指針的引用計(jì)數(shù)永遠(yuǎn)不可能下降為0,資源永遠(yuǎn)不會(huì)釋放。
運(yùn)行結(jié)果
I'm B B released A released可見(jiàn),這里的A和B都能被正確釋放了;
- 使用 std::tr1::enable_shared_from_this 作為基類。比如:
當(dāng)使用了 shared_ptr 的時(shí)候,我們可能需要在所有的地方都使用它,否則就不容易達(dá)到管理生存期的目的了。但有的時(shí)候,我們手頭上只有對(duì)象的原始指針,比如在對(duì)象的函數(shù)內(nèi)部,我們只有 this。這就迫切的需要一個(gè)功能:如何從對(duì)象的裸指針中,生成我們需要的 shared_ptr。
有人可能會(huì)覺(jué)得這個(gè)簡(jiǎn)單,shared_ptr a(this); 不就行了么?很遺憾的告訴你,這樣不行,會(huì)出問(wèn)題。為什么呢?因?yàn)檫@里的 a,手中對(duì) this 的引用計(jì)數(shù)只有 1,它無(wú)法知道其他地方智能指針對(duì) this 這個(gè)指針(就是這個(gè)對(duì)象)的引用情況,因此當(dāng) a 的生命周期結(jié)束(比如函數(shù)返回)的時(shí)候,this 就會(huì)被它毫不留情的釋放掉,其他地方的相關(guān)智能指針,手中拿著的該對(duì)象指針已經(jīng)變成非法。因此,我們需要使用std::tr1::enable_shared_from_this 作為基類將類的this指針的引用導(dǎo)出來(lái).
參考閱讀
轉(zhuǎn)載于:https://www.cnblogs.com/Stultz-Lee/p/9998527.html
總結(jié)
以上是生活随笔為你收集整理的使用TR1的智能指针的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Linux基础命令---comm
- 下一篇: 3012C语言_数据