天天看點

第三章 資源管理

十三、以對象管理資源

這裡用兩個智能指針做示範

class Investment
 {
     Initialization* CreateInvetment(); // 
 }
 void f()
 {
     Initialization* pInv = CreateInvetment(); // 調用 factory函數
     ...
     delete pInv; // 釋放pInv
 }      

上述代碼中,在建立指針和删除指針之間,有可能會因為種種原因(比如後人維護代碼過程中,執行了return語句),造成delete沒有被執行

解決辦法是以對象管理資源

void f()
 {
     std::auto_ptr<Initialization> pInv(CreateInvetment());
 }      

以對象管理資源的兩個關鍵技術思想

1、擷取到資源後立即放進管理對象

2、管理對象運用析構函數確定資源被釋放

注意;受auto_ptr管理的資源必須絕對沒有一個以上的auto_ptr同時指向它

舉例:

std::auto_ptr<Initialization> pInv1(CreateInvetment());
 std::auto_ptr<Initialization> pInv2(pInv1); // pInv2 指向對象,pInv1被設定為NULL
 pInv1 = pInv2; // pInv1指向對象,pInv2被設定為NUL      

L

引用計數型指針 RCSP (reference-counting smart pointer),RSCP也是個智能指針,持續追蹤共有多少個

對象指向某筆資源,并在無人通路它的時候自動删除該資源

void f()
 {
     std::tr1::shared_ptr<Initialization> pInv(CreateInvetment());
     std::shared_ptr<Initialization> pInv2(pInv1); // pInv1和pInv2指向同一對象
     pInv1 = pInv2; // pInv1和pInv2指向同一對象}      

總結:

1、為了防止資源洩漏請使用RALL對象,它們在構造函數中獲得資源并在析構中釋放資源

2、兩個常備使用的RALL call是突然::shared_ptr 和auto_ptr。前者

十四、在資源管理類中小心Coping行為

RALL (Resource Acquisition is Initialization),适用于heap-based資源上

但是并非所有的資源都是heap-based,對于這類資源,auto_ptr和tr1::shared_ptr這樣的隻能指針往往不适合作為資源管理者

在這種情況下,需要建立自己的資源管理類

總結:

在自己的資源管理類中,如果不希望發生對象的複制行為,将設定複制函數為private

十五、對原始資源的通路

顯示轉換和隐式轉換

隐式轉換就是不帶轉換類型的轉換,如int轉float你可以這樣子float a ;int b = 4;

a=b就是隐式轉換,而a = (float)b就是顯示轉換

總結:

1、API 往往要求通路原始資源,是以每一個RALL類應該提供一個"取得其所管理資源"的辦法

2、對原始資源的通路,可能經由顯式轉換或者隐式轉換,一般而言顯式轉換更安全,但隐式轉換對客戶來說更友善

十六、承兌使用new和delete是要采取相同形式 

當你使用了一個 new 表達式(也就是說,通過使用 new 動态建立一個對象),有兩件事情會發生。首先,配置設定記憶體

(通過一個被稱為 operator new 的函數——參見 Item 49 和 51)。第二,一個或多個構造函數在這些記憶體上被調用。

當你使用一個 delete 表達式(也就是說,使用 delete),有另外的兩件事情會發生:一個或多個析構函數在這些記憶體上被調用,

然後記憶體被回收

    new[]出來的對象,用delete釋放,可能隻釋放了一部分,

    new出來的對象,用delete[]釋放,可能将一塊記憶體釋放很多次

總結:

new\delete對應,和new[]\delete[] 對應

十七、在一個獨立的語句中,将new出來的對象存入隻能指針

"為什麼要這麼做?不這麼做會怎樣"

場景:

int priority();
     void processWidget(std::st1::shared_ptr<Widget> pw,int ipriority());      
A、
 <1>、調用priority
 <2>、執行"new Widget"
 <3>、調用tr1::shared_ptr構造函數
 B、
 <1>、執行"new Widget"
 <2>、調用priority
 <3>、調用tr1::shared_ptr構造函數      
shd::tr1::shared_ptr<Widget> pw(new Widget);
     processWidget(pw,ipriority());      

繼續閱讀