What is meant by Resource Acquisition is Initialization (RAII)?
What is meant by Resource Acquisition is Initialization (RAII)?
This is a programming idiom which briefly means that you
This guarantees that whatever happens while the resource is in use, it will eventually get freed (whether due to normal return, destruction of the containing object, or an exception thrown).
It is a widely used good practice in C++, because apart from being a safe way to deal with resources, it also makes your code much cleaner as you don't need to mix error handling code with the main functionality.
* Update: "local" may mean a local variable, or a nonstatic member variable of a class. In the latter case the member variable is initialized and destroyed with its owner object.
** Update2: as @sbi pointed out, the resource - although often is allocated inside the constructor - may also be allocated outside and passed in as a parameter.
An object's lifetime is determined by its scope. However, sometimes we need, or it is useful, to create an object that lives independently of the scope where it was created. In C++, the operator new is used to create such an object. And to destroy the object, the operator delete can be used. Objects created by the operator new are dynamically allocated, i.e. allocated in dynamic memory (also called heap or free store). So, an object that was created by new will continue to exist until it's explicitly destroyed using delete.
Some mistakes that can occur when using new and delete are:
new to allocate an object and forget to delete the object.delete the object, and then use the other pointer.delete an object twice.Generally, scoped variables are preferred. However, RAII can be used as an alternative to new and delete to make an object live independently of its scope. Such a technique consists of taking the pointer to the object that was allocated on the heap and placing it in a handle/manager object. The latter has a destructor that will take care of destroying the object. This will guarantee that the object is available to any function that wants access to it, and that the object is destroyed when the lifetime of the handle object ends, without the need for explicit cleanup.
Examples from the C++ standard library that use RAII are std::string and std::vector.
Consider this piece of code:
void fn(const std::string& str)
{
std::vector<char> vec;
for (auto c : str)
vec.push_back(c);
// do something
}
when you create a vector and you push elements to it, you don't care about allocating and deallocating such elements. The vector uses new to allocate space for its elements on the heap, and delete to free that space. You as a user of vector you don't care about the implementation details and will trust vector not to leak. In this case, the vector is the handle object of its elements.
Other examples from the standard library that use RAII are std::shared_ptr, std::unique_ptr, and std::lock_guard.
Another name for this technique is SBRM, short for Scope-Bound Resource Management.
There are three parts to an RAII class:
RAII stands for "Resource Acquisition is initialization." The "resource acquisition" part of RAII is where you begin something that must be ended later, such as:
The "is initialization" part means that the acquisition happens inside the constructor of a class.
Many argue that RAII is a misnomer, but actually it is a right name for this idiom, just it is not explained well.
Wikipedia explained behavior in detail: Resource acquisition is initialization (RAII) is a programming idiom used in several object-oriented, statically-typed programming languages to describe a particular language behavior. 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.
And now for the name, it simply means the action of "resource acquisition" is an action of initialization and should be part of the initialization/constructor of the resource class object. In other word, using this idiom, working with a resource means making a resource class to hold the resource and initialize resource at time of constructing the class object. Implicitly, it suggests the deallocation of the resource should happen symmetrically in the resource class destructor.
How is this useful? You can of course choose not to use this idiom, but if you wonder what you would get with this idiom, consider
RAII It is quite common for even larger C++ projects to not contain a single call to new or delete (or malloc/free) outside of a constructor/destructor pair. Or at all, in fact.
And you can avoid the
exit: free_resouce() // clean resource before exit function
or use a RAII lock so you never forget to unlock.
I've come back to this question several times and read it, and I think the highest voted answer is a little bit misleading.
They key for RAII is:
"It's (mostly) not about catching exceptions, it's mostly about managing ownership of resources."
The highest voted answer overstates exception-safe, which made me confused.
The fact is that:
You still need to write try catch to handle exceptions (check the 2 code example below), except that you don't need to worry about releasing resources for those classes using RAII in your catch block. Otherwise, you need to look up each non-RAII class's API to find which function to call so as to release acquired resources in catch block. RAII simply save these work.
Similar as above, when coding with RAII, you simply write less code, no need to call releasing resouce functions. All the clean-ups are done in the destructor.
Also, check these 2 code examples I found useful in comments above.
https://ideone.com/1Jjzuc , https://ideone.com/xm2GR9
P.S. One can compare with the python with .. as statement, you need to catch the exception which could take place inside the with block too.