Resource Acquisition Is Initialization(RAII Idiom)
2014-11-27 00:00
302 查看
原文链接:http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Resource_Acquisition_Is_Initialization
To provide basic exception safety guarantee
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.
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.
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-intrusive reference 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
Exception Safety: Concepts and Techniques, Bjarne Stroustrup
The RAII Programming Idiom
Sutter, Herb (1999). Exceptional C++. Addison-Wesley. ISBN 0-201-61562-2.
C++ Patterns: Execute Around Sequences, Kevlin Henney
Intent
To guarantee release of resource(s) at the end of a scopeTo provide basic exception safety guarantee
Also Known As
Execute-Around ObjectResource 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-intrusive reference 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++ softwarestd::auto_ptr
boost::scoped_ptr
boost::mutex::scoped_lock
Related Idioms
Scope GuardReference 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 on WikipediaException Safety: Concepts and Techniques, Bjarne Stroustrup
The RAII Programming Idiom
Sutter, Herb (1999). Exceptional C++. Addison-Wesley. ISBN 0-201-61562-2.
C++ Patterns: Execute Around Sequences, Kevlin Henney
相关文章推荐
- Resource Acquisition Is Initialization(RAII Idiom)
- Resource Acquisition Is Initialization(RAII Idiom)
- RAII -- Resource Acquisition Is Initialization
- The RAII(resource acquisition is initialization) of C++
- Resource Acquisition Is Initialization(RAII)
- 浅谈----RAII资源获得即初始化(Resource Acquisition Is Initialization)
- Resource Acquisition Is Initialization (RAII)是什么?(封装的优势)
- RAII(Resource Acquisition Is Initialization)资源获得式初始化
- RAII(Resource Acquisition Is Initialization:资源获取即初始化)
- RAII(Resource Acquisition Is Initialization资源获取即初始化 )思想
- RAII:资源获取即初始化(resourse acquisition is initialization)
- C++ “resource acquisition is initialization”
- RAII (Resource Acquirement Is Initialization)
- the requested resource servlet action is not available is not available的解决方案
- The resource is not on the build path of a java project
- 文件系统不同步问题resource is out of sync with the file sys
- Resource is out of sync with the file system
- 本地服务器打不开(或者 the target resource or is not willing to disclose that one exists.)
- The resource is not on the build path of a java project解决方法
- Resource '...' is out of sync with file system.