RAII(Resource Acquisition Is Initialization )机制是Bjarne Stroustrup首先提出的。要解决的是这样一个问题:
在C++(www.cppentry.com)中,如果在这个程序段结束时需要完成一些资源释放工作,那么正常情况下自然是没有什么问题,但是当一个异常抛出时,释放资源的语句就不会被执行。于是Bjarne Stroustrup就想到确保能运行资源释放代码的地方就是在这个程序段(栈帧)中放置的对象的析构函数了,因为stack winding会保证它们的析构函数都会被执行。将初始化和资源释放都移动到一个包装类中的好处:
- 保证了资源的正常释放
- 省去了在异常处理中冗长而重复甚至有些还不一定执行到的清理逻辑,进而确保了代码的异常安全。
- 简化代码体积。
1、应用场景
1)文件操作
我们可以是用这个机制将文件操作包装起来完成一个异常安全的文件类。实现上,注意将复制构造函数和赋值符私有化,这个是通过一个私有继承类完成的,因为这两个操作在此并没有意义,当然这并不是RAII所要求的。
- /*
- * =====================================================================================
- *
- * Filename: file.cpp
- *
- * Description: RAII for files
- *
- * Version: 1.0
- * Created: 05/09/2011 06:57:43 PM
- * Revision: none
- * Compiler: g++
- *
- * Author: gnuhpc (http://blog.csdn.net/gnuhpc), warmbupt@gmail.com
- *
- * =====================================================================================
- */
- #include
- #include
- #include
-
- using namespace std;
- class NonCopyable
- {
- public:
- NonCopyable(){};
- private:
- NonCopyable (NonCopyable const &); // private copy constructor
- NonCopyable & operator = (NonCopyable const &); // private assignment operator
- };
-
- class SafeFile:NonCopyable{
- public:
- SafeFile(const char* filename):fileHandler(fopen(filename,"w+"))
- {
- if( fileHandler == NULL )
- {
- throw runtime_error("Open Error!");
- }
- }
- ~SafeFile()
- {
- fclose(fileHandler);
- }
-
- void write(const char* str)
- {
- if( fputs(str,fileHandler)==EOF )
- {
- throw runtime_error("Write Error!");
- }
- }
-
- void write(const char* buffer, size_t num)
- {
- if( num!=0 && fwrite(buffer,num,1,fileHandler)==0 )
- {
- throw runtime_error("Write Error!");
- }
- }
- private:
- FILE *fileHandler;
- SafeFile(const SafeFile&);
- SafeFile &operator =(const SafeFile&);
- };
-
- int main(int argc, char *argv[])
- {
- SafeFile testVar("foo.test");
- testVar.write("Hello RAII");
- }
C++(www.cppentry.com)的结构决定了其原生支持RAII,而在Java 中,对象何时销毁是未知的,所以在Java 中可以使用try-finally做相关处理。