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.