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