Menu
Coddy logo textTech

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 released

Smart 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 icon

Challenge

Easy

Let'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 a Connection class that manages a connection resource using RAII principles. The class should have:
    • A private connectionId attribute (string) to identify the connection
    • A private isOpen attribute (bool) to track the connection state
    • A constructor that takes a connection ID, sets isOpen to true, and prints "Opening connection: <id>"
    • A destructor that checks if the connection is open, closes it by setting isOpen to 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
  • 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 Connection object 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"

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 released

Smart 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;
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming