《Effective C++ 中文版 第三版》讀書筆記
** 條款 13:以對象管理資源 **
Toby* CreateToby(); //< 返回指針,指向 Toby 繼承體系內(nèi)的動(dòng)態(tài)分配對象。調(diào)用者有責(zé)任刪除它。
void t()
{
Toby* pToby = CreateToby();
...
delete pToby;
}
如果 “...” 中的代碼含有 “return”、“goto” 或 “continue” 提早退出,還有可能是“...”區(qū)域內(nèi)拋出異常,若真是這樣,delete 語句就不會(huì)被執(zhí)行。
也許我們自己不會(huì)去加這些 “return”,但是代碼不是我們一個(gè)人的。因此單純的想 “f 總是會(huì)執(zhí)行 delete 語句” 是不可能的。
為確保 CreateToby() 返回的資源總是被釋放,我們需要將資源放進(jìn)對象中,這樣,對象的析構(gòu)函數(shù)會(huì)幫助我們自動(dòng)釋放這些資源。
void t()
{
std::auto_ptr<Toby> pToby(CreateToby());
...
}
這個(gè)簡單的例子示范 “以對象管理資源” 的兩個(gè)關(guān)鍵想法:
- 獲得資源后立刻放進(jìn)管理對象內(nèi),“資源取得時(shí)機(jī)便是初始化時(shí)機(jī)”(RAII);
- 管理對象運(yùn)用析構(gòu)函數(shù)確保資源被釋放。
由于 auto_ptr 被銷毀時(shí)會(huì)自動(dòng)刪除它所指之物,所以一定要注意別讓多個(gè) auto_ptr 同時(shí)指向同一個(gè)對象。為了預(yù)防這個(gè)問題,auto_ptr 有一個(gè)性質(zhì):若通過 copy 構(gòu)造函數(shù)或 copy 賦值操作符復(fù)制他們,他們會(huì)變成 null,而復(fù)制所得的指針將取得資源的唯一擁有權(quán)!
auto_ptr 的替代方案是“引用計(jì)數(shù)型智慧指針”,即 RCSP。其實(shí)質(zhì)也是一個(gè)智能指針,持續(xù)追蹤共有多少對象指向某筆資源,并在無人指向它時(shí)自動(dòng)刪除該資源。RCSP 類似垃圾回收,不同的是 RCSP 無法打破環(huán)狀引用,例如兩個(gè)其實(shí)已經(jīng)沒被使用的對象彼此互指,因而好像還處在“被使用”狀態(tài)。
TR1 的 tr1::shared_ptr 就是個(gè) RCSP,例如:
void t()
{
std::tr1::shared_ptr<Toby> pToby(CreateToby());
...
}
這段代碼看起來幾乎和使用 auto_ptr 的代碼相同,但是 shared_ptr 的復(fù)制行為正常多了。
請記住:
- 為了防止資源泄漏,請使用 RAII 對象,它們在構(gòu)造函數(shù)中獲得資源并在析構(gòu)函數(shù)中釋放資源。
- 兩個(gè)常被使用的 RAII class 分別是 tr1::shared_ptr 和 auto_ptr。前者通常是較佳選擇,因?yàn)槠?copy 行為比較直觀。若選擇 auto_ptr,復(fù)制動(dòng)作會(huì)使它(被復(fù)制物)指向 null。