天天看點

RAII技術

RAII(Resource acquisition is initialization)資源擷取即初始化,它是一項很簡單的技術,利用C++對象生命周期的概念來控制程式的資源,例如記憶體,檔案句柄,網絡連接配接以及審計追蹤(audit trail)等. 若希望保持對某個重要資源的跟蹤,那麼建立一個對象,并将資源的生命周期和對象的生命周期相關聯。即:調用類構造函數中初始化資源類對象,在調用類析構函數中釋放資源類對象。

簡單點就是:将堆對象交由棧來管理,棧是有生命周期的,不需要手動釋放記憶體。

應用場景:觀察下面這個例子

demo1:
class ResourceControl
{
    public:
    ResourceControl();
    ResourceControl(const ResourceControl&);
    ResourceControl& operator = (const ResourceControl&);
    ~ResourceControl();
    Resource* GetResource();
    void Work();
    private:
    Resource *rh_;
};
void ResourceControl::Work()
{
 rh_ = new Resource;
     //…
   if( //異常出現時,提前結束 ) //糟糕的維護
   {
        return;
   }

   //…

   delete rh_; //一定能執行到這裡嗎?
}
Resource * ResourceControl::GetResource( ) 
{
       return this->rh_;
}
           

由于程式可能提前return,delete rh_;語句執行不到,導緻資源沒有釋放。

解決方案:使用RAII技術,修改如下,将Resource 類對象放在構造函數中初始化,在析構函數中釋放。

class ResourceControl
{
    public:
    ResourceControl(Resource *rh);
    ResourceControl(const ResourceControl&);
    ResourceControl& operator = (const ResourceControl&);
    ~ResourceControl();
    Resource* GetResource();
    void Work();
    private:
    Resource *rh_;
};
ResourceControl::ResourceControl(Resource *rh):rh_(rh)
{
    //其他初始化工作
}
ResourceControl::~ResourceControl()
{
    delete   this->rh_;
    //其他初始化工作
}
Resource* GetResource()
{
  return this->rh_;
}
           

接下來還有一個重要的問題,如何保證析構函數肯定被調用到?

ResourceControl對象的最美妙之處在于,若它被聲明為一個函數的局部變量,或作為函數的參數,或是一個靜态對象,即棧對象,那麼就可以保證析構函數會得到調用。堆對象則必須要顯示調用delete。

ResourceControl* rc = new ResourceControl( new Resource ); //糟糕的思路

以下是參考的博文位址:

http://blog.csdn.net/armman/article/details/1547651#comments

繼續閱讀