條款13 以物件管理資源

2021-09-08 21:51:51 字數 1883 閱讀 8661

所謂有資源,就是你一旦使用了它,就要記得歸還系統。如果不這樣做,就會發生資源的浪費。這裡的資源不僅僅是指記憶體,也包括:檔案描述符,互斥鎖,資料庫連線…

本條款是乙個直接而易懂的基於物件的資源管理方法,建立在c++對建構函式,析構函式,copy函式的基礎上。經驗顯示,經過訓練後嚴守這些做法,可以幾乎消除資源管理的問題。下面我們就開始了~~~~~

首先,我們以工廠模式來說起:

假如我們使用乙個用來模擬投資行為的程式庫,其中各式各樣的投資型別繼承自乙個root class investment;

classinvestment{};

進一步假設,這個程式庫是通過乙個工廠函式**我們某特定的investment物件:

investment* createinvestment(){}//返回指標,指向investment繼承體系內的動態分配物件。呼叫者有責任刪除它,這裡為了簡化,不寫引數。

現在考慮有個f函式履行了這個責任:

voidf()

這似乎看起來很美好,但是不幸的事情發生了,它發生在「…」**中,可能是return了,也可能是出現了異常,總之,沒有執行到delete上。我們洩露的不只是那些記憶體塊,還有那些投資物件所儲存的任何資源。

現在的問題是pinve和delete不在同乙個物件,如果它們在同乙個物件,我們完全可以依靠物件的析構函式來進行析構。因此……..

我們可以用標準庫提供的auto_ptr。這是乙個類指標物件。也就是所謂的智慧型指標。其析構函式自動對其所指物件呼叫delete。

voidf()

這個簡單的例子示範「以物件管理資源」的兩個關鍵想法:

l  獲得資源後,立刻放進管理物件內。

在以上**中,createinvestment返回的資源被當作其管理者auto_ptr的初值。實際上「以物件管理資源」的觀念常被稱為「資源獲取時機便是初始化時機」(resource acquisition is initializatioin, raii).

l  管理物件運用析構函式確保資源被釋放。

由於auto_ptr被銷毀時,會自動刪除它所指之物,所以一定要注意別讓多個auto_ptr同時指向同乙個物件。如果真是那樣,物件會被刪除一次以上,會造成未定義行為。為了預防這個問題,auto_ptr有乙個不尋常的性質:若通過copy函式複製它們,它們會變成null,而複製所得的指標將取得資源的唯一擁有權。如下:

std::auto_ptrpinv(createinvestment());//pinv point to a investment obj

std::auto_ptrpinv2(pinv);//pinv2 point to obj, pinv is null

pinv=pinv2();//pinv piont to obj, pinv2 is null

這一詭異的複製行為,復加上其底層亂條件:「受auto_ptr管理的資源必須絕對沒有乙個以上的auto_ptr同時指向它」。但是在stl中,容器要求其元素發揮「正常的」複製行為,因此這些容器不得auto_ptr。

auto_ptr的乙個替代方案就是「引用計數型智慧型指標(reference-counting smart pointer, rcsp)」。所謂的rcsp也是乙個智慧型指標。持續追蹤共有多少個物件指向某筆資源,並在無人指向它時,自動刪除該資源。

voidf()

auto_ptr 和trl::shared_ptr兩者都在其析構函式內做delete而不是delete動作。那意味著在動態分配而得到的array身上使用auto_ptr 和trl::shared_ptr是個壞主意。

請記住:

l   為防止資源洩露,請使用raii物件,它們在建構函式中獲得資源並在析構函式中釋放資源。

l   兩個常使用的raii classes 分別是auto_ptr 和trl::shared_ptr。後者是乙個較佳的選擇。因為其copy行為比較直觀。若選擇前者,複製動作會使它指向null。

條款13 以物件管理資源

問題 解決 智慧型指標。把資源放入物件內,利用析構函式確保釋放。1 資源取得時機便是初始化時機 resource acquisition is initialization raii 2 管理物件運用析構函式確保資源被釋放。別讓auto ptr同時指向同一物件。為了預防這個問題,能過copy建構函式...

條款13 以物件管理資源

我們都知道,當new乙個東西之後,必須delete它。但是問題可能出現在在new和delete之間 比如中間出現了異常,或者return之類的。一種比較好的作法是通過物件來管理 因為當物件的宣告週期結束以後,會呼叫析構函式,而在析構函式中delete,這樣的作法就靠譜多了。在標準c 中,定義了2種管...

條款13 以物件管理資源

一 如下 假設各種子型別繼承 root class investmen class investment investment createinevstment factory函式 void f 在 區域內乙個過早return,或者期間丟擲異常,流程控制不可能經過這條語句,所以這樣的話就會導致資源洩...