RAII in C++
Part of the Object Oriented Programming section of Coddy's C++ journey — lesson 16 of 104.
RAII (Resource Acquisition Is Initialization) is a fundamental C++ idiom where resource management is tied to object lifetime. The idea is simple: acquire resources in the constructor, release them in the destructor.
When an object is created, it acquires whatever resources it needs. When the object goes out of scope, its destructor automatically releases those resources. This guarantees cleanup even if exceptions occur.
class FileHandler {
std::FILE* file;
public:
FileHandler(const char* filename) {
file = std::fopen(filename, "r"); // Acquire resource
}
~FileHandler() {
if (file) std::fclose(file); // Release resource
}
};With RAII, you never forget to clean up:
void processFile() {
FileHandler handler("data.txt"); // Resource acquired
// Work with file...
// If exception thrown here, destructor still runs!
} // Resource automatically releasedSmart pointers are the perfect example of RAII in action. A unique_ptr acquires ownership of heap memory in its constructor and deletes it in its destructor. You've already been using RAII without realizing it!
RAII applies to any resource: memory, file handles, network connections, mutexes, or database connections. By wrapping resources in objects, C++ ensures deterministic cleanup and eliminates entire categories of bugs like leaks and dangling handles.
Challenge
EasyLet's build a connection manager that demonstrates RAII by automatically handling the lifecycle of network-like connections. When a connection is created, it should "open," and when it goes out of scope, it should automatically "close" — no manual cleanup required!
You'll create two files to organize your code:
Connection.h: Define aConnectionclass that manages a connection resource using RAII principles. The class should have:- A private
connectionIdattribute (string) to identify the connection - A private
isOpenattribute (bool) to track the connection state - A constructor that takes a connection ID, sets
isOpento true, and prints"Opening connection: <id>" - A destructor that checks if the connection is open, closes it by setting
isOpento false, and prints"Closing connection: <id>" - A
send(string message)method that prints"[<id>] Sending: <message>"if the connection is open - A
getId()method that returns the connection ID
- A private
main.cpp: Demonstrate how RAII ensures automatic cleanup by reading a connection ID and a message from input. Then:- Create a scope using curly braces
{ } - Inside that scope, create a
Connectionobject on the stack with the input ID - Use the connection to send the input message
- Let the scope end (the connection should automatically close)
- After the scope, print
"Connection out of scope"
- Create a scope using curly braces
The beauty of RAII is that you don't need to remember to close the connection — the destructor handles it automatically when the object leaves scope. This pattern prevents resource leaks even if something unexpected happens in your code.
Include your header file in main.cpp using #include "Connection.h".
Cheat sheet
RAII (Resource Acquisition Is Initialization) is a C++ idiom where resource management is tied to object lifetime. Resources are acquired in the constructor and released in the destructor.
When an object goes out of scope, its destructor automatically releases resources, guaranteeing cleanup even if exceptions occur:
class FileHandler {
std::FILE* file;
public:
FileHandler(const char* filename) {
file = std::fopen(filename, "r"); // Acquire resource
}
~FileHandler() {
if (file) std::fclose(file); // Release resource
}
};RAII ensures automatic cleanup:
void processFile() {
FileHandler handler("data.txt"); // Resource acquired
// Work with file...
// If exception thrown, destructor still runs!
} // Resource automatically releasedSmart pointers like unique_ptr are examples of RAII. They acquire heap memory in the constructor and delete it in the destructor.
RAII applies to any resource: memory, file handles, network connections, mutexes, or database connections. It ensures deterministic cleanup and eliminates bugs like leaks and dangling handles.
Try it yourself
#include <iostream>
#include <string>
#include "Connection.h"
using namespace std;
int main() {
string connectionId;
string message;
// Read input
cin >> connectionId;
cin.ignore();
getline(cin, message);
// TODO: Create a scope using curly braces { }
// Inside the scope:
// - Create a Connection object on the stack with connectionId
// - Use the connection to send the message
// Let the scope end (destructor will be called automatically)
// TODO: After the scope ends, print "Connection out of scope"
return 0;
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesC++ Build & CompilationHeader Files & Source FilesNamespaces & ScopeIntroduction to OOP in C++Classes vs ObjectsThe 'this' PointerMethods (Member Functions)Attributes (Data Members)Ctors & Dtors BasicsRecap - Simple Calculator4Class Properties
Instance vs Static MembersGetters and SettersConst Member FunctionsMutable KeywordStatic Methods and VariablesFriend Functions & ClassesRecap - Bank Account Manager7Inheritance
Basic InheritanceInheritance Access LevelsCtor & Dtor Call OrderMethod OverridingVirtual Functions & VTableMultiple InheritanceVirtual InheritanceRecap - Employee Hierarchy2Memory Management
Stack vs Heap MemoryPointers and ReferencesDynamic Memory (new/delete)Smart Pointers in C++RAII in C++Recap - Dynamic Array Manager5Encapsulation
Access Specifiers in C++Access Specifiers In DepthInformation HidingStruct vs ClassNested & Inner ClassesRecap - Student Records System8Polymorphism
Compile vs Runtime PolymorphFunction OverloadingVirtual Functions RevisitedPure Virtual FunctionsAbstract ClassesInterface Design in C++Dynamic Casting & RTTIRecap - Shape Calculator3Constructors & Destructors
Default ConstructorParameterized ConstructorCopy ConstructorMove ConstructorConstructor Init ListsDelegating ConstructorsDestructor Deep DiveRule of Three / Five / ZeroRecap - String Class6Operator Overloading
Intro to Operator OverloadArithmetic Operator OverloadComparison Operator OverloadStream OperatorsAssignment Operator Overload[] and () Operator OverloadType Conversion OperatorsRecap - Matrix Class9Templates
Function TemplatesClass TemplatesTemplate SpecializationVariadic TemplatesSFINAE & Type Traits BasicsRecap - Generic Container