RAII in C++ – When to Use Resource Acquisition Is Initialization

cidiomsobject-oriented-designraii

I understand the concept of RAII:
Use the destructor as a means to free resources, such as memory, or closing file handles/database connections. Coming from a Java background this was actually rather easy to understand because of the similarities to finally.

However, I do not quite understand when you actually should apply it. Obviously it should be implemented when initializing objects on the heap, but what are the other scenarios a normal programmer would have to use it for? Looking at this thread I found out that for example std::ifstream already has RAII implemented to handle the freeing of its file handle. So wrapping it in another object just to call ifstreamObj.close() in its destructor would be a waste of time. But I am pretty sure that this is not a general rule that applies to all of the libraries out there.

So my question is: when should I actually use RAII? Is there a general rule of thumb, a best-practice, or do I have to crawl through each and every class's documentation if I want to be sure? Or can I be certain that every class that implements a close()/free()/delete() (or something similar) method also takes care of calling it properly when necessary?

Best Answer

when should I actually use RAII?

When you acquire any resource in the member functions of your class and haven't delegated the responsibility to release those resources to another object/function, you need to make sure that you release those resources in the destructor.

If your class acquires a file handle by using std::ifstream::open(), you shouldn't have to explicitly call std::ifstream::close() since the destructor of std::ifstream will take care of it, i.e. the responsibility has been delegated to another object.

However, if your class acquires a file handle by using fopen(), you will have to make sure that destructor of your class calls fclose() appropriately.

Is there a general rule of thumb, a best-practice, or do I have to crawl through each and every class's documentation if I want to be sure?

As a rule of thump, you should assume that each class that you use, whether they are from the standard library, a vendor's library, or in-house library, adheres to the principle. If it doesn't, it's a defect and must be fixed by the party responsible for it.

You shouldn't have to call std::ifstream::close(). If the file doesn't get closed, you should inform the vendor that they need to fix the problem. In the mean time, you should write a wrapper class that takes care of the problem and use the wrapper class in rest of your code.