RAII

Posted simple_孙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RAII相关的知识,希望对你有一定的参考价值。

全称是Resource Acquisition is Initialization,翻译为资源获取就是初始化。

其实就是利用栈上的局部对象在离开作用域时会自动释放的原理,在临时对象创建时初始化资源,或者将资源交给对象管理,当临时对象析构时释放资源,因为临时对象在离开其作用时会自动析构,也就会自动释放其对应资源。

适用于对异常状况的处理,如果用try..catch或条件判断处理异常,除了在所有可能出现异常的位置要添加这些处理语句之外,还要手工的去释放相应的资源。有了RAII,只需要在一个作用域内将资源交给一个临时对象,就可以了,跳出该作用域时系统会自动资源。

可以用于对内存,文件句柄,网络套接字,互斥锁等资源的管理

对在堆上分配的资源,可用如下类管理

class RAIIBase  

{  

protected:  

    RAIIBase(){}  

    ~RAIIBase(){}  

private:      

    RAIIBase (const RAIIBase &);  

    RAIIBase & operator = (const RAIIBase &);  

    void * operator new(size_t size);   

    // 不定义任何成员  

};  

 

template<typename T>  

class ResourceHandle: public RAIIBase //私有继承 禁用Base的所有继承操作  

{  

public:  

    explicit ResourceHandle(T * aResource):r_(aResource){}//获取资源  

    ~ResourceHandle() {delete r_; } //释放资源  

    T *get()    {return r_ ;} //访问资源  

private:  

    T * r_;  

};

 

对于文件句柄的操作

http://www.cnblogs.com/hsinwang/articles/214663.html

class FileHandle {
public:
    FileHandle(char const* n, char const* a) { p = fopen(n, a); }
    ~FileHandle() { fclose(p); }
private:
    // 禁止拷贝操作
    FileHandle(FileHandle const&);
    FileHandle& operator= (FileHandle const&);
    FILE *p;
};

RAII惯用法同样适用于需要管理多个资源的复杂对象。例如,Widget类的构造函数要获取两个资源:文件myFile和互斥锁myLock。每个资源的获取都有可能失败并且抛出异常。为了正常使用Widget对象,这里我们必须维护一个不变式(invariant):当调用构造函数时,要么两个资源全都获得,对象创建成功;要么两个资源都没得到,对象创建失败。获取了文件而没有得到互斥锁的情况永远不能出现,也就是说,不允许建立Widget对象的半成品。如果将RAII惯用法应用于成员对象,那么我们就可以实现这个不变式:

class Widget {
public:
    Widget(char const* myFile, char const* myLock)
    : file_(myFile),     // 获取文件myFile
      lock_(myLock)      // 获取互斥锁myLock
    {}
    // ...
private:
    FileHandle file_;
    LockHandle lock_;
};

FileHandleLockHandle类的对象作为Widget类的数据成员,分别表示需要获取的文件和互斥锁。资源的获取过程就是两个成员对象的初始化过程。在此系统会自动地为我们进行资源管理,程序员不必显式地添加任何异常处理代码。例如,当已经创建完file_,但尚未创建完lock_时,有一个异常被抛出,则系统会调用file_的析构函数,而不会调用lock_的析构函数。Bjarne所谓构造函数和析构函数与异常处理的交互作用,说的就是这种情形。

综上所述,RAII的本质内容是用对象代表资源,把管理资源的任务转化为管理对象的任务,将资源的获取和释放与对象的构造和析构对应起来,从而确保在对象的生存期内资源始终有效,对象销毁时资源必被释放。换句话说,拥有对象就等于拥有资源,对象存在则资源必定存在。由此可见,RAII惯用法是进行资源管理的有力武器。C++程序员依靠RAII写出的代码不仅简洁优雅,而且做到了异常安全。难怪微软的MSDN杂志在最近的一篇文章中承认:若论资源管理,谁也比不过标准C++”

以上是关于RAII的主要内容,如果未能解决你的问题,请参考以下文章

C++RAII机制(智能指针原理)

c++智能指针的不断演化

Constructor Acquires, Destructor Releases Resource Acquisition Is Initialization