Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

What's RAII All About?

Last updated Jan 1, 2003.

RAII is a widely-used idiom in C++. However, there's some confusion and misconceptions about this idiom so it's time to demystify it.

Is RAII a Synonym for Smart Pointers?

Textbooks and articles say that in order to implement RAII, one needs to have something like auto_ptr, shared_ptr , unique_ptr so that when the objects get destructed, the resource should be de-allocated automatically. What if I have a raw pointer? My code ensures that the pointer is released in case of exception (say in destructor). Likewise, my constructor takes care of initializing that pointer. Does that constitutes RAII or do I need to use one of the standard smart pointer classes mentioned above?

This is a very good question. The C++ literature often implies that RAII is all about smart pointers. It also implies that smart pointers are standard class templates. Both these statements are inaccurate. RAII is an acronym originally introduced in one of the earlier editions of Bjarne Stroutsrup's The C++ Programming Language. It stands for "resource acquisition is initialization"; a phrase whichI find a bit lacking. For starters, it focuses only on one of the two essential components of RAII -- initialization. Secondly, even that part isn't described clearly. First, let's see what RAII is not.

It's not Necessarily About Pointers

RAII is often used for automating memory management and avoiding memory leaks. However, the idiom itself has nothing to do with memory or with pointers. RAII is a very general concept that applies to what you can generally define as transactions. I will get to that in a moment. Suffice it to say that files, threads, database transactions, network data exchange and even getting a scoop of ice-cream from your freeze are all instances of RAII operations, or transactions.

It's not Necessarily about Exceptions

While exception present the biggest challenge for avoiding resource leaks, RAII isn't necessarily confined to programs that use exception handling (directly or indirectly). In fact, most RAII implementations are simply meant to remove the burden of manual resource release from the programmer, regardless of exceptions. RAII is more about automation, less about exceptions.

It's not Necessarily about Standard Classes

You don't have to use a standard class such as auto_ptr, ifstream, string or vector to achieve RAII (yes, all of these classes do implement RAII). You can write your own classes with RAII in mind.

What's in a Transaction?

Now let's see what RAII truly is. Many programming tasks and real-life tasks constitutes of three distinct operations, two of which are essential. I will refer to these tasks as transactions.

Initialization. Before you access a resource, say write data to a file, lick cold ice-cream or take a shower, you need to perform a certain initial operation: open the freezer's door, open the file, allocate memory from somewhere, instantiate a thread object, turn the car-keys in the switch etc.

Usage. The second step consists of using the resource acquired in step 1. That means for example, taking out the ice-cream box outside the freezer (something you can do only after opening the freezer's door), write data to a file that you've just opened, write data to a memory address that you've just allocated, and so on. In some cases, the usage part doesn't exist.

Release. Whether your task includes the usage part or not, a transaction requires an explicit release operation. The release phase usually undoes the effects of the initialization: it closes the freezer's door, releases a memory locks, frees memory allocated from the heap, closes a file (even if you haven't read or written anything), commits or rolls back a database transaction and so on.

RAII packs these essential initialization and release phases into a class' constructor and destructor, respectively. The usage part is often implemented as a distinct member function (write(), execute_thread(), query the database, send a packet of data to a socket, or fill your glass with some scoops of ice-cream). We can conclude that RAII exists in any class whose destructor releases whatever its constructor has acquired.

C++ is one of the few languages that support RAII. Why is this? In order to implement RAII, you need destructors. While every OOP language has constructors, very few of them have proper destructors. Recall that finalizers are not destructors because finalizers are optional and they are non-deterministic. You can't tell when exactly a finalizer will run -- in five seconds, in two years or indeed, never.

Back to the original question, the answer is positive. If you have a class whose constructor allocates memory and whose destructor releases that memory, then you have RAII. Of course, it's more convenient to use a ready-made standard class that already implements this functionality, say unique_ptr. However, if you prefer to use your own classes for automating the handling of transactions, that would make perfect RAII.