effective C++ 讀書筆記 條款14 以對象管理資源
如果我們使用一個投資行為的程序庫:
#include "stdafx.h" #include <iostream> #include <memory> using namespace std; class Investment { public: }; class InvestmentFactory { public: virtual Investment* createInvestment() { Investment * inV = NULL; return inV; } }; //第一版,這裏可能發生內存泄露,比方在調用createInvestmen()之後到delete pInv之間的函數體之間發生了異常或者調用了return等 //那麽delete語句將不會被運行,早成內存泄露 void f() { InvestmentFactory fac; Investment* pInv = fac.createInvestment(); delete pInv; } int _tmain(int argc, _TCHAR* argv[]) { return 0; }
//第一版,這裏可能發生內存泄露,比方在調用createInvestmen()之後到delete pInv之間的函數體之間發生了異常或者調用了return等
//那麽delete語句將不會被運行,早成內存泄露
<span style="color:#3333ff;">void f() { InvestmentFactory fac; Investment* pInv = fac.createInvestment(); delete pInv; }</span>
//第二版:為了確保createInvestment返回的資源總是被釋放,我們須要將資源放進對象內。當控制流離開f,該對象的析構函數會自己主動釋放那些資源
//auto_ptr是個類指針對象,也就是所謂的“智能指針”。其析構函數會自己主動對其所指對象調用delete。
<span style="color:#3333ff;">void f() { InvestmentFactory fac; std::auto_ptr<Investment> pInv(fac.createInvestment());//調用factory函數,一如既往的使用pInv。經由auto_ptr的析構函數自己主動刪除pInv }</span>
//上面第二版“以對象管理資源”的兩個關鍵想法
1:獲得資源後馬上放進管理對象:以上代碼createInvestmen返回的資源被當做其管理者auto_ptr的初值。
對象資源管理的觀念也被稱為
資源取得實際便是初始化時機。由於我們總是在獲得一筆資源後於允許語句內以它初始化某個管理對象
2:管理對象運用析構函數確保資源被釋放
//第二版存在的問題:
//因為auto_ptr被銷毀時會自己主動刪除它所指之物,所以一定要註意別讓多個auto_ptr同一時候指向某一對象。假設真是這樣。對象會被刪除一次以上,程序
//出現沒有定義行為,為了防止這個問題,auto_ptr有一個不平常的性質:若通過copy構造函數或者copy assigment操作符復制他們,他們會變為null
//而復制所得的指針將取得資源的唯一全部權。
auto_ptr<Investmen> pInv1(fac.createInvestment()); pInv1指向資源
auto_ptr<Investment> pInv2(pInv1); pInv2指向資源pInv1為NULL
pInv1 = pInv2; pInv1指向對象,pInv2成為null
//第三版:
<span style="color:#3333ff;">void f() { InvestmentFactory fac; std::shared_ptr<Investment> pInv1(fac.createInvestment());//調用factory函數。一如既往的使用pInv,經由shared_ptr的析構函數自己主動刪除pInv tr1::shared_ptr<Investment> pInv2(pInv1);//pInv1 和 pInv2 指向一個資源對象 pInv2 = pInv1;//同上,無不論什麽改變 //當pInv1 and pInv2 銷毀的時候,它們所指的對象也被自己主動銷毀 }</span>
/*
第三版能夠正常使用,也是最佳版本號。 可是註意auto_ptr and shared_ptr在析構函數其中都是做的 delete而不是delete[],所以不要把
動態分配而得的array用在auto_ptr and shared_ptr身上。
*/
總結:
為防止資源泄露,請使用對象管理資源,他們在構造函數其中獲得資源。並在析構函數其中釋放資源
兩個經常使用的RAII class 為 tr1::shared_ptr and auto_ptr;第一個是最佳選擇由於其copy行為比較直觀,若選擇auto_ptr復制動作會使得它指向null。
effective C++ 讀書筆記 條款14 以對象管理資源