Resource Acquisition is Initialization (or RAII for short, usually pronounced by simply spelling out the letters R-A-I-I) is a programming technique where we make sure that resources are cleaned up when they are no longer needed by tying a resource to an object. The resource is kept as long as the object is alive and automatically released when the object is destroyed.
The resource that is being managed can be a segment of memory, a file handle, a network socket, a database handle or anything else which there is just a limited number of in the system and which we need to make sure we close properly after we are done with it.
The way RAII works is that we tie the resource to a class. When an instance of the class is created then the constructor of the object’s class is called to create the resource (or passed the resource to be managed). When the object is later destroyed (by going out of scope) then the destructor will automatically be called and here we write the code to release the resource again.
The name is somewhat difficult and controversial, some have suggested instead calling it Scope-Bound Resource Management but this has so far not been too successful.
I think an example of what I mean is necessary here. In the example below is a segment of memory allocated (using new[]) in the constructor of the File class and the memory is released again (using delete[]) in the destructor. The neat thing here is that the destructor will automatically be called when the object goes out of scope, as is done when the function main() in the example exits.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
class File { private: char* m_name; public: File(const char* name = 0) { if(nullptr == name) { m_name = ""; } else { size_t length = sizeof(name); m_name = new char[length]; for(size_t index = 0; index < length; ++index) { m_name[index] = name[index]; } } } ~File() { delete[] m_name; } }; int main() { File f("C++"); // this calls the constructor of File return 0; } // here the object 'f' goes out of scope and the destructor is called |
Notice: this is only done automatically for you if the File object is allocated as a local object, this is one of the reasons why you should never use new or delete.
The benefits of RAII is that it creates:
- exception safety: a stack object will be destroyed at the end of the enclosing scope, also if an exception is thrown from the code after the object is created.
- good locality: the code for allocating the resource is in the same class as the code for releasing the resource again.
- encapsulation: the managed resource is located inside the owning class and not accessible outside of it.
Because of its benefits is RAII used extensively throughout the standard library classes.
As an example, the following code is using old C functions to write data to a text file NOT using RAII.
|
// NOT Exception safe method for writing text to file. NOT using RAII void writeToFile(const char* fileName, const char* text) { // open the file FILE* f = fopen(fileName, "w"); if(nullptr != f) { fprintf(f, text); // close the file fclose(f); } } |
In the example above we didn’t use RAII to hold on to the resource (which in this case is the file handle FILE* f). This makes the code not exception safe, if anyone would later add a function call after the file has been opened and this method throws an exception then the call to fclose will not be executed at all, leaving the file opened and locked.
A better example is to instead use the standard library to open and write to the file:
|
// Exception safe method for writing text to file. using RAII void writeToFile(const char* fileName, const char* text) { // open the file for writing std::ofstream f(fileName, std::ios::out); f << text; } // end of scope, the file will be closed |
in this example does the instance of the standard library class std::ofstream which we create on the first line hold on to the file resource and when the object goes out of scope when the function ends then the file will be closed automatically for us. Notice how much shorter and cleaner this code becomes. We don’t have to worry about closing the file since this is done for us.
References
- Stroustrup: Why doesn’t C++ provide a “finally” construct?


