effective C++ 條款 13:以對象管理資源

來源:互聯網
上載者:User

資源是,一旦用了,將來必須還給系統,除了記憶體常見的還有檔案描述符(file description)、互斥鎖、圖形介面中的筆刷、資料庫連接

以及網路socket。考慮到異常、函數內多重回傳路徑、程式維護員軟體改動卻沒有理解隨之而來的衝擊,發現資源管理的特殊手段還不很充分夠用。

假設一個各式各樣的投資類型繼承的一個root class Investment:

class Investment {...};

假設通過一個工廠函數供應我們某特定的Investment對象:

Investment* createInvestment();//返回指向Investment繼承體系的動態指派至。調用者有責任刪除它。

void f()
{
    Investment* pInv = createInvestment();  //調用factory函數
    ...
    delete pInv;   //釋放pInv所指對象
}

若果…中有一個過早的return語句,或者拋出異常,那麼控制流程將不會幸臨delete。

為確保資源總是被釋放,我們需要將資源放進對象內,這樣便可依賴c++的“解構函式自動調用機制”確保資源被釋放。標準程式庫提供的auto_ptr正是針對這種形勢設計的特製產品。auto_ptr是一個“類指標(pointer-like)對象”:

void f()
{
    std::auto_ptr<Investment> pInv(createInvestment());
    ...
}  //經由auto_ptr的解構函式自動刪除pInv

1.獲得資源後立即放進管理對象(managing object)內。createInvestment返回的資源被當做其管理者auto_ptr的初值。

“以對象管理資源”的觀念常被稱為“資源取得時便是初始化時”(resource Acquisition is Initialization;RAII),有時獲得的資源拿來賦值(而非初始化)某個管理對象,但不論哪種做法,每筆資源在獲得的同時立刻被放進管理對象中。

2.管理對象運用解構函式確保資源被釋放。一旦對象被銷毀(當對象離開範圍),其解構函式自然會自動調用,於是資源被釋放。

由於autu_ptr被銷毀時會自動刪除它所指之物,所以一定不要讓多個auto_ptr同時指向同一個對象。為防止這個問題,auto_ptr有一個不尋常的性質:若通過copy建構函式或copy assignment操作符複製它們,它們會變成null,而複製所得的指標取得資源的唯一使用權。

std::auto_ptr<Investment> pInv1(createInvestment());
std::auto_ptr<Investment> pInv2(pInv1);//現在pInv2指向對象,pInv1被設為null
pInv1 = pInv2;//現在pInv1指向對象,pInv2被設為null

這個詭異的複製行為,使得要求其元素髮揮“正常的”複製行為的像stl容器這種容不得auto_ptr。

auto_ptr的替代方案是“引用計數型智慧指標”(reference-counting smart pointer;RCSP)PCSP持續追蹤共有多少對象指向

某筆資源,並在無人指向它時刪除該資源。類似於記憶體回收,但無法打破環狀引用(cycle of reference,例如兩個其實已經沒有被使用的對象彼此互指,因而好像在“被使用”狀態)。

TR1的tr1:shared_ptr就是個RCSP,所以可以這麼寫f:

void f()
{
    std::tr1::shared_ptr<Investment> pInv(createInvestment());
    ...
}//經由shared_ptr的解構函式自動刪除pInv

shared_ptr的複製正常多了

void f()
{
    std::tr1::shared_ptr<Investment> pInv1(createInvestment());
    std::tr1::shared_ptr<Investment> pInv2(pInv1);//pInv1和pInv2指向同一個對象
    pInv1 = pInv2;
    ...
}//pInv1和pInv2被銷毀,他們指向的對象也就被銷毀。

所以shared_ptr可以被用於stl容器及其他“auto_ptr之非正統複製行為並不合適”的語境上。

auto_ptr及shared_ptr在其解構函式內做delete而不是delete[]動作。那意味著在動態分配而得的array身上使用auto_ptr或shared_ptr是個餿主意。因為vector和string幾乎總是可以替代動態分配而得的數組。boost::scope_array 和boost::shared_array classes是針對數組設計的類似auto_ptr和tr1::shared_ptr那樣的類。

為防止資源泄漏,請使用RAII對象,他們在建構函式中獲得資源並在解構函式中釋放資源。shared_ptr比auto_ptr是個較佳的選擇

因為其copy行為比較直觀。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.