Resource Acquisition Is Initialization (RAII)
Is a C++ programming technique.
That class constructor acquires the resources and establish all the class invariants or throw an exception if that can not be done, and the destructor releases the resource and never throws exception.
It ensures that resources are automatically acquired when an object is created and automatically released when the object goes out of scope.
C++ have built in RAII tools in STL
void processFile() {
FILE* file = fopen("data.txt", "r");
// If this throws an exception or returns early,
// the file handle leaks!
if (!file) return;
// Do work...
fclose(file); // Error-prone manual cleanup
}
#include <iostream>
#include <fstream>
#include <string>
void processFileRAII() {
// Resource acquired and initialized here
std::ifstream file("data.txt");
if (!file.is_open()) return;
// Do work...
} // File is AUTOMATICALLY closed here when 'file' goes out of scope
// mutex example from cppreference.com
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(); // if bad() 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 good() returns normally, the mutex is released
#include <iostream>
class Widget {
public:
Widget() { std::cout << "Widget acquired\n"; }
~Widget() { std::cout << "Widget destroyed\n"; }
};
void badExample() {
// RAW POINT: Manual allocation
Widget* w = new Widget();
// Potential early exit
bool error = true;
if (error) {
return; // ❌ LEAK: Memory is never freed!
}
// Manual cleanup required
delete w;
}
#include <iostream>
#include <memory> // Required for smart pointers
class Widget {
public:
Widget() { std::cout << "Widget acquired\n"; }
~Widget() { std::cout << "Widget destroyed\n"; }
};
void goodExample() {
// SMART POINT: Automatic RAII allocation
std::unique_ptr<Widget> w = std::make_unique<Widget>();
// Potential early exit
bool error = true;
if (error) {
return; // SAFE: Destructor runs automatically, memory freed!
}
} // SAFE: Destructor runs here if code reaches the end