天天看點

Effective C++之3 資源管理

資源為系統所擁有,在借用資源後必須歸還給系統。主要的資源包括:記憶體、檔案描述符、互斥鎖、圖形界面中的字型、資料庫連接配接、網絡socket。

條款13:以對象管理資源

在對象中用指針管理的記憶體(例如在運作過程中動态配置設定的記憶體),使用者極易遺忘其釋放,或者很難把握其釋放時間,進而造成記憶體洩露,可通過用對象管理資源來保證其正常的運作,即使用智能指針,在對象銷毀時自動調用智能指針的内在方法來析構其指向的動态記憶體。

以對象管理資源有兩個特點:

a)       獲得資源後立即放進對象,也即可稱為“資源擷取時機便是初始化時機”(RALL),因為總是在獲得一筆資源後于同一語句内用來初始化某個管理對象。

b)       管理對象運用析構函數確定對象被釋放。即對象被銷毀時其析構函數會自動被調用,于是資源釋放。

主要的包括指針指針:析構函數自動釋放器所指向的記憶體。

l  指針指針包括auto_ptr,如std::auto_ptr<sutdet> pStu(CreateStudent());其中student為類名,此處表示智能指針的類型但是通過拷貝構造函數和等号操作符來複制這種類型的指針時,上一個指針會變為NULL,即始終隻能有一個指針指向對象。

l  其替代方案是使用“應用計數型智慧指針“(RCSP),如tr1::shared_ptr,其使用方法:

如std:: tr1::shared_ptr<sutdet> pStu(CreateStudent());

條款14:在資源管理類中小心copy行為

面對一個RAII對象被複制會發生什麼情況的問題,即調用拷貝構造函數。有兩種可能,禁止複制和對底層資源祭出應用計數法。

Class Lock

{

         Public:

                  Explicit Lock(Mutex* pm):mutexPtr(pm,unlock)    //構造并以unlock為删除器

{lock(mutexPtr.get());  

}

         Private:

                  Std::tr1::share_ptr<Mutex> mutexPtr;

}

MutexPtr的析構函數會在互斥器的引用次數為0時自動調用tr1::shared_ptr的删除器(本例為unlock),拷貝其對象會增加其引用計數。

複制RAII對象必須一并複制它所管理的資源,是以資源的copying行為決定RAII對象的copying行為。

條款15:在資源管理類中提供對原始資源的通路

Tr1::shared_ptr和auto_ptr都提供一個get成員函數,用來執行顯示轉換,也就是可以傳回智能指針内部的原始指針。Int day = dayHeld(pInv.get);其中pInv為智能指針。

也可通過一個接口來封裝這個顯示轉換,使其使用比較便捷,但是可能導緻對資源應用的誤用。

條款16:成對使用new和delete時要采取相同形式

l  當你使用new運算符時,有兩件事情發生。第一:記憶體被配置設定出來;第二:針對此記憶體有一個或多個構造函數被調用。調用delete時同理,先析構後釋放。

l  在申請時使用的數組形式,在釋放時也應該采用數組形式,前後形式應該一緻。

條款17:以獨立語句獎罰newed對象置入智能指針

以獨立語句将newed對象儲存(置入)智能指針中。如果不這樣做,一旦異常被抛出,有可能導緻難以察覺的資源洩露。

因為如此可以将執行順序固定為先動态配置設定記憶體、調用tr1::shared_ptr構造函數、調用功能函數。否則第二步和第三步的執行順序并不能保證。

如processWidget(std::tr1::shared_ptr<widget> (new widget));

應當轉換為:

std::tr1::shared_ptr<widget> pw(new widget);

processWidget(pw);

繼續閱讀