請牢記:java
以獨立語句將newed對象存儲於(置入)智能指針內。若是不這樣作,一旦異常被跑出來,有可能致使難以察覺的資源泄露。c++
假設有個函數用來處理程序的優先權,另外一個函數用來在某動態分配所得的Widget上進行某些帶有優先權的處理:c#
int priority(); //處理程序優先權的函數
void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);//該函數在動態分配所得的Widget上進行某些帶有優先權的處理。
調用:函數
processWidget(new Widget, priority()); //編譯不過!該構造函數是explicit 沒法隱式轉換爲shared_ptr
所以能夠寫成:spa
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority()); //能夠編譯經過,可是...可能泄露資源。
後果:一旦發生異常,可能資源泄露指針
緣由:對象
在調用processWidget以前,編譯器必須建立代碼,執行三步:blog
(1)調用prority()ci
(2)執行"new Widget"資源
(3)調用 tr1"shared_ptr構造函數
可是c++調用順序跟java和c#不一樣,不是以特定順序完成。priority函數的調用有可能在第1、第二或者第三執行。當在第二位執行的狀況下:
(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()); // 這個動做不會形成泄露
由於編譯器對於」跨越語句的各項操做「沒有從新排列的自由(只有在語句內編譯器才擁有那個自由度)。