原文链接:http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Resource_Acquisition_Is_Initialization

Intent

  • To guarantee release of resource(s) at the end of a scope
  • To provide basic exception safety guarantee

Also Known As

  • Execute-Around Object
  • Resource Release Is Finalization
  • Scope-Bound Resource Management

Motivation

Resources acquired in a function scope should be released before leaving the scope unless the ownership is being transferred to another
scope or object. Quite often it means a pair of function calls - one to acquire a resource and another one to release it. For example, new/delete, malloc/free, acquire/release, file-open/file-close, nested_count++/nested_count--, etc. It is quite easy to forget
to write the "release" part of the resource management "contract". Sometimes the resource release function is never invoked: this can happen when the control flow leaves the scope because of return or an exception. It is too dangerous to trust the programmer
that he or she will invoke resource release operation in all possible cases in the present and in the future. Some examples are given below.

void foo ()
{
char * ch = new char [100];
if (...)
if (...)
return;
else if (...)
if (...)
else
throw "ERROR"; delete [] ch; // This may not be invoked... memory leak!
}
void bar ()
{
lock.acquire();
if (...)
if (...)
return;
else
throw "ERROR"; lock.release(); // This may not be invoked... deadlock!
}

This is in general control flow abstraction problem. Resource Acquisition is Initialization (RAII) is an extremely popular idiom in C++
that relieves the burden of calling "resource release" operation in a clever way.

Solution and Sample Code

The idea is to wrap the resource release operation in a destructor of an object in the scope. Language guarantees that the destructor will
always be invoked (of a successfully constructed object) when control flow leaves the scope because of a return statement or an exception.

//  Private copy constructor and copy assignment ensure classes derived
// from class NonCopyable cannot be copied.
class NonCopyable
{
NonCopyable (NonCopyable const &); // private copy constructor
NonCopyable & operator = (NonCopyable const &); // private assignment operator
};
template <class T>
class AutoDelete : NonCopyable
{
public:
AutoDelete (T * p = 0) : ptr_(p) {}
~AutoDelete () throw() { delete ptr_; }
private:
T *ptr_;
}; class ScopedLock : NonCopyable// Scoped Lock idiom
{
public:
ScopedLock (Lock & l) : lock_(l) { lock_.acquire(); }
~ScopedLock () throw () { lock_.release(); }
private:
Lock& lock_;
}; void foo ()
{
X * p = new X;
AutoDelete<X> safe_del(p); // Memory will not leak
p = 0;
// Although, above assignment "p = 0" is not necessary
// as we would not have a dangling pointer in this example.
// It is a good programming practice. if (...)
if (...)
return; // No need to call delete here.
// Destructor of safe_del will delete memory
}
void X::bar()
{
ScopedLock safe_lock(l); // Lock will be released certainly
if (...)
if (...)
throw "ERROR";
// No need to call release here.
// Destructor of safe_lock will release the lock
}

Acquiring resource(s) in constructor is not mandatory in RAII idiom but releasing resources in the destructor is the key. Therefore, it is also known (rarely though) as Resource Release is Finalization idiom.
It is important in this idiom that the destructor should not throw exceptions. Therefore, the destructors have no-throw specification but it is optional. std::auto_ptr and boost::scoped_ptr are ways of quickly using RAII idiom for memory resources. RAII is
also used to ensure exception safety. RAII makes it possible to avoid resource leaks without extensive use of try/catch blocks and is widely used in the software industry.

Many classes that manage resources using RAII, do not have legitimate copy semantics (e.g., network connections, database cursors, mutex). The NonCopyable class shown before prevents copying of objects that
implement RAII. It simply prevents access to the copy-constructor and the copy-assignment operator by making them private. boost::scoped_ptr is an example of one such class that prevents copying while holding memory resources. The NonCopyable class
states this intention explicitly and prevents compilation if used incorrectly. Such classes should not be used in STL containers. However, every resource management class that implements RAII does not have to be non-copyable like the above two examples. If
copy semantics are desired, boost::shared_ptr can be used to manage memory resources. In general, non-intrusivereference counting is used to provide copy semantics as well as RAII.

Consequences

RAII is not without its limitations. The resources which are not memory and must be released deterministically and may
throw exceptions usually aren't handled very well by C++ destructors. That's because a C++ destructor can't propagate errors to the enclosing scope (which is potentially winding up). It has no return value and it should not propagate exceptions outside itself.
If exceptions are possible, then the destructor must handle the exceptional case within itself somehow. Nevertheless, RAII remains the most widely used resource management idiom in C++.


Known Uses

  • Virtually all non-trivial C++ software
  • std::auto_ptr
  • boost::scoped_ptr
  • boost::mutex::scoped_lock

Related Idioms

Scope Guard

Reference Counting

Non copyable
Scoped
Locking
 idiom is a special case of RAII applied to operating system synchronization primitives such as mutex and semaphores

Reference






Resource Acquisition Is Initialization(RAII Idiom)的更多相关文章

  1. Constructor Acquires, Destructor Releases Resource Acquisition Is Initialization

    w https://zh.wikipedia.org/wiki/RAII RAII要求,资源的有效期与持有资源的对象的生命期严格绑定,即由对象的构造函数完成资源的分配(获取),同时由析构函数完成资源的 ...

  2. RAII(Resource Acquisition Is Initialization)简介

    RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源.避免泄漏的惯用法.C++标准保证任何情况下,已构造的 ...

  3. RAII(Resource Acquisition Is Initialization)资源获得式初始化

    当在编写代码中用到异常,非常重要的一点是:“如果异常发生,程序占用的资源都被正确地清理了吗?” 大多数情况下不用担心,但是在构造函数里有一个特殊的问题:如果一个对象的构造函数在执行过程中抛出异常,那么 ...

  4. Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring-mybatis.xml]: Initialization of bean failed

  5. <Effective C++>读书摘要--Resource Management<一>

    1.除了内存资源以外,Other common resources include file descriptors, mutex locks, fonts and brushes in graphi ...

  6. C++学习指南

    转载于stackoverflow:http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list 感谢Ge ...

  7. The Definitive C++ Book Guide and List

    学习c++的书单 转自 http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list Beginner ...

  8. More C++ Idioms

    Table of Contents Note: synonyms for each idiom are listed in parentheses. Adapter Template TODO Add ...

  9. The Definitive C++ Book Guide and List--reference

    http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list Reference Style - All ...

随机推荐

  1. jetty 9 嵌入式开发示例

    jetty 9 嵌入应用程序后,小型的web应用直接打成一个单独的jar包,就可以直接运行,非常适合做Demo演示或云端集群部署. 主要代码: JettyServer的封装类 package yjmy ...

  2. PHP操作MySQL数据库5个步骤

    PHP操作MySQL数据库一般可分为5个步骤:1.连接MySQL数据库服务器:2.选择数据库:3.执行SQL语句:4.关闭结果集:5断开与MySQL数据库服务器连接. 1.用mysql_connect ...

  3. 【原】Learning Spark (Python版) 学习笔记(二)----键值对、数据读取与保存、共享特性

    本来应该上周更新的,结果碰上五一,懒癌发作,就推迟了 = =.以后还是要按时完成任务.废话不多说,第四章-第六章主要讲了三个内容:键值对.数据读取与保存与Spark的两个共享特性(累加器和广播变量). ...

  4. html 元素分类

    在讲解CSS布局之前,我们需要提前知道一些知识,在CSS中,html中的标签元素大体被分为三种不同的类型:块状元素.内联元素(又叫行内元素)和内联块状元素. 常用的块状元素有: <div> ...

  5. ceph rgw s3 java sdk 上传大文件分批的方法

    Using the AWS Java SDK for Multipart Upload (High-Level API) Topics Upload a File Abort Multipart Up ...

  6. 移动端浏览器和微信浏览器上禁止body的滚动条

    一般禁止body滚动的做法就是设置overflow:hidden. 但是很奇怪的发现在移动端浏览器和微信浏览器上这个不起作用,然后我分析了我的写法,就是在body上加了一个class去定义属性,然后改 ...

  7. 【CityHunter】基于LBS的AR体感游戏设计理念

    本人目前还不是游戏行业的圈内人士,并不懂得,游戏行业的生态圈,也不懂得,所谓的什么“中国市场环境”.所以不敢发表关于这方面的见解,不过我在这里想要插一句话,就是我认为啊,行业内,人与人之间还是有分层次 ...

  8. json使用

    json是存储和交换文本信息的语法,类似 XML,比 XML 更小.更快,更易解析 json 可通过 JavaScript 进行解析 json 数据可使用 AJAX 进行传输 //读取var JSON ...

  9. sql中的inner join ,left join ,right join

    左连接LEFT JOIN, 也就是说,左外连接的含义是限制连接关键字右端的表中的数据必须满足连接条件,而不关左端的表中的数据是否满足连接条件,均输出左端表中的内容.不满足连接条件的 ,连接字段栏位将对 ...

  10. jquery实现简单瀑布流布局(续):图片懒加载

    # jquery实现简单瀑布流布局(续):图片懒加载 这篇文章是jquery实现简单瀑布流布局思想的小小扩展.代码基于前作的代码继续完善. 图片懒加载就是符合某些条件时才触发图片的加载.最常见的具体表 ...