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_;
};

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

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

时间: 2024-12-18 02:57:54

RAII的相关文章

RAII手法封装相互排斥锁

CriticalSectionWrapper是一个接口类 class CriticalSectionWrapper { public: // Factory method, constructor disabled static CriticalSectionWrapper* CreateCriticalSection(); virtual ~CriticalSectionWrapper() {} // Tries to grab lock, beginning of a critical se

使用智能指针来管理对象 (基于RAII)

////一个简单的防止内存泄露的例子//void test() { //使用RAII的特性管理资源 //当智能指针unique_ptr被销毁时,它指向的对象也将被销毁 //这里test函数返回后 p将自动销毁 //unique_ptr<int[]> p( new int[200] ); //直接生成资源 //test函数返回后 p不能被正常销毁,就会造成资源泄露 //int* p = new int[200]; } int main() { while( 1 ) { test(); Sleep

浅谈RAII&智能指针

关于RAII,官方给出的解释是这样的"资源获取就是初始化".听起来貌似不是很懂的哈,其实说的通俗点的话就是它是一种管理资源,避免内存泄漏的一种方法.它可以保证在各种情况下,当你对对象进行使用时先通过构造函数来进行资源的分配和初始化,最后通过析构函数来进行清理,有效的保证了资源的正确分配和释放.(特别是在异常中,因为异常往往会改变代码正确的执行顺序,这就很容易引起资源管理的混乱和内存的泄漏) 其中智能指针就是RAII的一种实现模式,所谓的智能就是它可以自动化的来管理它所指向那份空间的资源

RAII惯用法

RAII,也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源.避免内存泄露的方法.简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构的时候释放资源. 例如,我们无需直接调用一对非成员函数OpenPort/ClosePort,而是可以考虑定义常性且内部初始化的RAII概念的“端口”操作类: class Port{ public: Port(const string& destination);//调用OpenPor

C++之RAII技术解析

1.什么是RAII 技术? 我们在C++中经常使用new申请了内存空间,但是却也经常忘记delete回收申请的空间,容易造成内存溢出,于是RAII技术就诞生了,来解决这样的问题.RAII(Resource Acquisition Is Initialization)机制是Bjarne Stroustrup首先提出的,是一种利用对象生命周期来控制程序资源(如内存.文件句柄.网络连接.互斥量等等)的简单技术. 我们知道在函数内部的一些成员是放置在栈空间上的,当函数返回时,这些栈上的局部变量就会立即释

Linux封装之四:RAII实现MutexLock自动化解锁

在实现线程的过程中,我们经常会写类似于这样的代码: { mutex_.lock(); //XXX if(...) 语句; //XXX mutex_.unlock(); } 虽然这段代码是正常的加锁解锁,但是有时候我们难免会出现一些低级错误,例如把 忘了写mutex_.unlock().那么我们该如何防止这种错误呢? 我们可以采用和实现智能指针相似的办法,把加锁和解锁封装在同一个对象中. 实现“对象生命期”等于“加锁.解锁周期” . 代码如下; 1 //类的关联 2 class MutexGuar

C++ 资源管理之 RAII

RAII,它是"Resource Acquisition Is Initialization"的首字母缩写.也称为"资源获取就是初始化",是c++等编程语言常用的管理资源.避免内存泄露的方法.它保证在任何情况下,使用对象时先构造对象,最后析构对象. RAII的好处在于它提供了一种资源自动管理的方式,当产生异常.回滚等现象时,RAII可以正确地释放掉资源. 当讲述C++资源管理时,Bjarne这样写道: 使用局部对象管理资源的技术通常称为"资源获取就是初始化

RAII&智能指针

智能指针是C++中为了实现资源的有效管理而被提出的,我们可以创建它但无须操心它的释放问题,在引入异常机制的程序里它是十分有用的,或者说,对于博主这中粗心大意的人来说还是可以偶尔使用的.他可以在一些场合防止内存泄漏的问题.但是,智能指针也是存在着许多的问题,所以许多的编程规范里告诫我们少使用智能指针,但对于我们来说,必须了解它的原理. *RAII:资源获得即初始化,我们在构造函数里将其初始化,并在析构函数里释放它 eg:一个简单的AutoPtr的实现 template<class T> clas

C++ RAII手法实现的线程安全的日志文件写例子

#include <iostream> #include <fstream> #include <string> #include <cstdarg> #include <cstdio> #include <pthread.h> // MutexLock 封装互斥锁的接口 class MutexLock { public: MutexLock() { pthread_mutex_init(&mutex_, NULL); } M