假設有個函數用來處理程序的優先權,另一個函數用來在某動態分配所得的Widget上進行某些帶有優先權的處理:
int priority(); //處理程序優先權的函數
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);//該函數在動態分配所得的Widget上進行某些帶有優先權的處理。
調用:
processWidget(new Widget, priority()); //編譯不過!該構造函數是explicit 無法隱式轉換為shared_ptr
因此可以寫成:
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); //可以編譯通過,但是...可能洩露資源。
後果:一旦發生異常,可能資源洩露
原因:
在調用processWidget之前,編譯器必須創建代碼,執行三步:
(1)調用prority()
(2)執行"new Widget"
(3)調用 tr1"shared_ptr構造函數
但是c++調用順序跟java和c#不同,不是以特定順序完成。priority函數的調用有可能在第一、第二或者第三執行。當在第二位執行的情況下:
(1)執行"new Widget"
(2)調用prority()
(3)調用 tr1"shared_ptr構造函數
若調用prority時發生異常,則"new Widget"返回的指針將會遺失,這樣會引發資源洩露。
解決方案:使用分離語句,分別寫出(1)創建Widget,(2)將它置入一個智能指針內,然後再把那個智能指針傳給processWidget:
std::tr1::shared_ptr<Widget> pw(new Widget); //在單獨語句內以智能指針存儲newed所得對象
processWidget(pw, priority()); // 這個動作不會造成洩露
因為編譯器對於”跨越語句的各項操作“沒有重新排列的自由(只有在語句內編譯器才擁有那個自由度)。