Resource acquisition is initialization (RAII) is a programming idiom used in several object-oriented, statically-typed programming languages to describe a particular language behavior. (C 语言没有构造析构函数,就不能直接用RAII)
In RAII, holding a resource is a class invariant, and is tied to object lifetime: resource allocation (or acquisition) is done during object creation (specifically initialization), by the constructor, while resource deallocation (release) is done during object destruction (specifically finalization), by the destructor.
In other words, resource acquisition must succeed for initialization to succeed. Thus the resource is guaranteed to be held between when initialization finishes and finalization starts (holding the resources is a class invariant), and to be held only when the object is alive. Thus if there are no object leaks, there are no resource leaks.
RAII is associated most prominently with C++ where it originated, but also other lanaguages. The technique was developed for exception-safe resource management in C++ during 1984–89, primarily by Bjarne Stroustrup and Andrew Koenig, and the term itself was coined by Stroustrup, RAII is generally pronounced as an initialism, sometimes pronounced as "R, A, double I".
C++11 example
The following C++11 example demonstrates usage of RAII for file access and mutex locking:
#include <fstream> #include <iostream> #include <mutex> #include <stdexcept> #include <string> void WriteToFile(const std::string& message) { // |mutex| is to protect access to |file| (which is shared across threads). static std::mutex mutex; // Lock |mutex| before accessing |file|. std::lock_guard<std::mutex> lock(mutex); // Try to open file. std::ofstream file("example.txt"); if (!file.is_open()) { throw std::runtime_error("unable to open file"); } // Write |message| to |file|. file << message << std::endl; // |file| will be closed first when leaving scope (regardless of exception) // |mutex| will be unlocked second (from lock destructor) when leaving scope // (regardless of exception). }
This code is exception-safe because C++ guarantees that all stack objects are destroyed at the end of the enclosing scope, known as stack unwinding. The destructors of both the lock and file objects are therefore guaranteed to be called when returning from the function, whether an exception has been thrown or not.
Local variables allow easy management of multiple resources within a single function: they are destroyed in the reverse order of their construction, and an object is destroyed only if fully constructed—that is, if no exception propagates from its constructor.
Using RAII greatly simplifies resource management, reduces overall code size and helps ensure program correctness. RAII is therefore recommended by industry-standard guidelines,[15] and most of the C++ standard library follows the idiom.
What is RAII?
https://medium.com/swlh/what-is-raii-e016d00269f9https://medium.com/swlh/what-is-raii-e016d00269f9
To RAII or Not to RAII?
To RAII or Not to RAII? - Fluent C++https://www.fluentcpp.com/2018/02/13/to-raii-or-not-to-raii/
A typical case for RAII: smart pointers
Smart pointers are classes that contain a pointer and take care of deleting them when going out of scope. If this sentence doesn’t make sense, you can look at this refresher on smart pointers, where we get into more details about the stack, the heap, and the principle of RAII illustrated with smart pointers.(这里明确了RAII 和smart pointers的关系: smart pointer是 RAII的一个usecase)
异常发生,还会退出作用域?
todo verify:
The destructors of both the lock and file objects are therefore guaranteed to be called when returning from the function, whether an exception has been thrown or not.