RAII

From cppreference.com
< cpp‎ | language
 
 
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Initialization
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 

"Resource Acquisition Is Initialization" or RAII, is a C++ programming technique[1] which binds the life cycle of a resource (memory allocation, socket, open file, mutex, database connection - anything that exists in limited supply) to the lifetime of an object with automatic storage duration, which guarantees that all resources are cleaned up when the object goes out of scope, in reverse order of acquisition. This leverages the language to eliminate resource leaks and guarantee exception safety. Another name for this technique is "Scope-bound resource management" (SBRM).

RAII can be summarized as follows:

  • encapsulate each resource into a class, where
  • the constructor acquires the resource and establishes all class invariants or throws an exception if that cannot be done
  • the destructor always releases the resource
  • always use the resource via an instance of a RAII-class that either
  • has automatic storage duration
  • is a non-static member of a class whose instance has automatic storage duration

Classes with open()/close(), lock()/unlock(), or init()/copyFrom()/destroy() member functions are typical examples of non-RAII classes:

std::mutex m;
void bad() 
{
    m.lock(); // acquire the mutex
    f();      // if f() throws an exception, the mutex is never released
    if(!everything_ok()) return; // early return, the mutex is never released
    m.unlock(); // only if the code reaches this statement, the mutex is released
}
void good()
{
    std::lock_guard<std::mutex> lk(m); // RAII class: mutex acquisition is initialization
    f(); // if f() throws an exception, the mutex is released
    if(!everything_ok()) return; // early return, the mutex is released
} // if the function returns normally, the mutex is released

[edit] The standard library

The C++ library classes that manage their own resources follow RAII: std::string, std::vector, std::thread, and many others allocate their resources in constructors (which throw exceptions on errors), release them in their destructors, and don't require explicit cleanup.

In addition, the standard library offers several RAII wrappers to manage user-provided resources:

[edit] References

  1. RAII in Stroustrup's C++ FAQ