天天看點

條款13(二):以對象管理資源條款13:以對象管理資源1,為了防止資源洩漏,請使用RAII對象,它們在構造函數中獲得資源并在析構函數中釋放資源。2,兩個常被使用的RAII classes分别是auto_ptr和tr1::shared_ptr。一般來說,後者是較佳的選擇,因為其copy行為比較直覺。若選擇auto_ptr,複制動作會使它(被複制物)指向null。

條款13:以對象管理資源

Use objects to manage resources.

RCSP

對于auto_ptr,它的替代方案是:

  • 引用計數型智慧指針(reference-counting smart pointer,RCSP)

所謂的RCSP,也是一個智能指針,持續追蹤共有多少對象指向某筆資源,并在無人指向它的時候自動删除該資源。

是以,RCSP所聽的行為類似于垃圾回收(garbage collection),不同之處在于RCSP**無法打破環狀引用(cycles of references,例如兩個其實已經沒有被使用的對象彼此互指,因而呈現出它們好像還處于“被引用”的狀态)。**

TR1的

tr1::shared_ptr

就是一個RCSP,是以可以這樣構造f函數:

void f()
{
    ...
    std::tr1::shared_ptr<Investment> pInv(createInvestment());  //調用factory函數,使用pInv
    ...                                                         //經由shared_ptr析構函數會自動删除pInv
}
           

這段代碼,和auto_ptr的版本幾乎一緻,但是對于shared_ptr而言,複制操作就正常了許多:

void f()
{
    ...
    std::tr1::shared_ptr<Investment> pInv1(createInvestment());    //pInv1指向createInvestment傳回物

    std::tr1::shared_ptr<Investment> pInv2(pInv1);     //(copy構造)pInv1和pInv2指向同一個對象

    pInv1 = pInv2;     //(copy assignment)同上,pInv1和pInv2指向同一個對象
    ...
}       //pInv1和pInv2都被銷毀,它們所指的對象也被自動銷毀了
           

是以,由于tr1::shared_ptr的複制行為“屬于正常”行為,是以它們可以被用于STL容器以及其他的“因auto_ptr的非正常指派行為而産生不适用”的情景中。

對于auto_ptr和tr1::shared_ptr而言,二者在析構函數内實作的,都是delete而非delete[ ]動作。是以,這就意味着:

  • 不要在動态配置設定而得的array上使用auto_ptr或者tr1::shared_ptr。

例如,以下代碼就是錯誤的:

str::auto_ptr<std::string> aps(new std::string[]);//錯誤!使用了錯誤的delete

std::tr1::shared_ptr<int> spi(new int[]);//同樣的錯誤
           

對此,并不存在特别為C++動态配置設定數組而設計的類似于auto_ptr或者tr1::shared_ptr這類東西,因為vector和string幾乎總是可以取代動态配置設定而得到的數組。

另外,如果打算手工釋放資源(例如使用delete而非使用一個資源管理類(resource-managing class)),這樣做是很容易發生錯誤的。設計這樣的資源管理類,需要注意很多的細節,這些内容會在條款14和15中講到。

關于createInvestment,它所傳回的是“未加工的指針(raw pointer)”,這對與資源洩漏是一個極大的隐患,因為調用者極易在這個指針身上忘記調用delete。即使使用了這一類的智能指針來執行這種delete,也必首先記的将createInvestment的傳回值存儲在智能指針對象内。

最後:

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

2,兩個常被使用的RAII classes分别是auto_ptr和tr1::shared_ptr。一般來說,後者是較佳的選擇,因為其copy行為比較直覺。若選擇auto_ptr,複制動作會使它(被複制物)指向null。