假設(shè)我們有個(gè)函數(shù)用來揭示處理程序的優(yōu)先權(quán),另一個(gè)函數(shù)用來在某動(dòng)態(tài)分配所得的widget上進(jìn)行某些帶有優(yōu)先權(quán)的處理:
void priority();
void processWidget(std::tr1::shared_ptr<Widget>pw, int priority);
由于謹(jǐn)記“以對象管理資源”(條款13)的智慧銘言,processwidget決定對其動(dòng)態(tài)分配得來的widget運(yùn)用智能指針(這里采用trl::shared_ptr)。
現(xiàn)在考慮調(diào)用processwidget:
processWidget(new Widget, priority());
等等,不要考慮這個(gè)調(diào)用形式。它不能通過編譯。tr1::shared ptr構(gòu)造函數(shù)需要一個(gè)原始指針(raw pointer),但該構(gòu)造函數(shù)是個(gè)explicit構(gòu)造函數(shù),無法進(jìn)行隱式轉(zhuǎn)換,將得自"newWidget"的原始指針轉(zhuǎn)換為processwidget所要求的tr1::shared ptr。如果寫成這樣就可以通過編譯:
processWidget(std::tr1::shared_ptr<Widget>pw, int priority);
令人驚訝的是,雖然我們在此使用“對象管理式資源”( object-managingresources) ,上述調(diào)用卻可能泄漏資源。稍后我再詳加解釋。
編譯器產(chǎn)出一個(gè)processWidget調(diào)用碼之前,必須首先核算即將被傳遞的各個(gè)實(shí)參。上述第二實(shí)參只是一個(gè)單純的對 priority函數(shù)的調(diào)用,但第一實(shí)參由兩部分組成:std::trl::shared ptr<Widget> (new widget)
- 執(zhí)行"new widget”表達(dá)式
- 調(diào)用tr1::shared ptr構(gòu)造函數(shù)
于是在調(diào)用processwidget之前,編譯器必須創(chuàng)建代碼,做以下三件事:
- 調(diào)用priority
- 執(zhí)行"new widget"
- 調(diào)用tr1::shared ptr構(gòu)造函數(shù)
C++編譯器以什么樣的次序完成這些事情呢?彈性很大。這和其他語言如Java和C#不同,那兩種語言總是以特定次序完成函數(shù)參數(shù)的核算。可以確定的是“newwidget”一定執(zhí)行于tr1::shared ptr構(gòu)造函數(shù)被調(diào)用之前,因?yàn)檫@個(gè)表達(dá)式的結(jié)果還要被傳遞作為tr1::shared_ptr構(gòu)造函數(shù)的一個(gè)實(shí)參,但對priority的調(diào)用則可以排在第---或第二或第三執(zhí)行。如果編譯器選擇以第二順位執(zhí)行它(說不定可因此生成更高效的代碼,誰知道!),最終獲得這樣的操作序列:
- 執(zhí)行"new widget"
- 調(diào)用priority
- 調(diào)用tr1: :shared ptr構(gòu)造函數(shù)
現(xiàn)在請你想想,萬一對priority的調(diào)用導(dǎo)致異常,會(huì)發(fā)生什么事?在此情況下"new widget”返問的指針將會(huì)遺失,因?yàn)樗形幢恢萌雝r1 : :shared ptr內(nèi),后者是我們期盼用來防衛(wèi)資源泄漏的武器。是的,在對processwidget的調(diào)用過程中可能引發(fā)資源泄漏,因?yàn)樵凇百Y源被創(chuàng)建(經(jīng)由"new widget")”和“資源被轉(zhuǎn)換為資源管理對象”兩個(gè)時(shí)間點(diǎn)之間有可能發(fā)生異常干擾。
避免這類問題的辦法很簡單:使用分離語句,分別寫出(1)創(chuàng)建widge,(2)將它置入一個(gè)智能指針內(nèi),然后再把那個(gè)智能指針傳給processwidget:
std::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());
以上之所以行得通,因?yàn)榫幾g器對于“跨越語句的各項(xiàng)操作”沒有重新排列的自由(只有在語句內(nèi)它才擁有那個(gè)自由度)。在上述修訂后的代碼內(nèi),"new Widget"表達(dá)式以及“對tr1:: shared_ptr構(gòu)造函數(shù)的調(diào)用”這兩個(gè)動(dòng)作,和“對priority的調(diào)用”是分隔開來的,位于不同語句內(nèi),所以編譯器不得在它們之間任意選擇執(zhí)行次序。文章來源:http://www.zghlxwxcb.cn/news/detail-672951.html
請記住文章來源地址http://www.zghlxwxcb.cn/news/detail-672951.html
- 以獨(dú)立語句將newed對象存儲(chǔ)于(置入)智能指針內(nèi)。如果不這樣做,一旦異常被拋出,有可能導(dǎo)致難以察覺的資源泄漏。
到了這里,關(guān)于Effective C++條款17——以獨(dú)立語句將newed 對象置入智能指針(資源管理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!