《Effective C++ 中文版 第三版》讀書筆記
** 條款 17:以獨立語句將 newed 對象置入智能指針 **
proToby(std::tr1::shared_ptr<Widget>(new Widget), priority());
在調(diào)用 proToby 之前,編譯器必須創(chuàng)建代碼,做以下三件事:
- 調(diào)用 priority
- 執(zhí)行 “new Widget”
- 調(diào)用 tr1::shared_ptr 構造函數(shù)
C++ 編譯器會以什么樣的順序完成這些事情呢?彈性很大。這和其他語言如 Java 和 C# 是不同的,后兩者總是以特定的次序完成函數(shù)參數(shù)的構造??梢源_定的是 “new Widget” 一定執(zhí)行于 tr1::shared_ptr 構造函數(shù)被調(diào)用之前,因為這個表達式的結果還要被傳遞作為 tr1::shared_ptr 構造函數(shù)的一個實參,但是對調(diào)用 priority 則可以排在第一、第二或者第三位執(zhí)行。若編譯器,恰巧把調(diào)用 priority 排在了第二位。最終獲得這樣的操作序列:
- 執(zhí)行 “new Widget”
- 調(diào)用 priority
- 調(diào)用 tr1::shared_ptr 構造函數(shù)
現(xiàn)在想一個問題:萬一對 priority 的調(diào)用導致異常,會發(fā)生什么事?此時,“new Widget” 返回的指針將會遺失,因為他未被置入 tr1::shared_ptr 內(nèi),后者是我們用來期盼用來方位資源泄漏的武器。但是從這個可能的情況中,我們發(fā)現(xiàn):在對 proToby 的調(diào)用過程中可能引發(fā)資源泄漏,因為在“資源被創(chuàng)建(經(jīng)由 “new Widget”)”和“資源被轉(zhuǎn)換為資源管理對象”兩個時間點之間有可能發(fā)生異常干擾。
避免的辦法:使用分離語句,分別寫出(1)創(chuàng)建 Widget,(2)將它置入一個智能指針內(nèi),然后再把那個智能指針傳給 proToby:
std::tr1::shared_ptr<Widget> pT(new Widget);
proToby(pT,priority());
這樣之所以可行,因為編譯器對于“跨越語句的各項操作”沒有重新排列的自由(只有在語句內(nèi)他才有這個自由)。
** 請記?。?**
以獨立語句將 newed 對象存儲于(置入)智能指針內(nèi)。如果不這樣做,一旦異常被拋出,有可能導致難以察覺的資源泄漏。