Destructors and the Magic of RAII
Object Oriented Programming and RAII

4.2 Destructors and the Magic of RAII

Resource Acquisition Is Initialization (RAII) is C++'s crowning design pattern. It links the lifetime of system resources (such as file handles, database connections, mutex locks, and heap memory) to the lifetime of stack variables. Because C++ guarantees that stack variables are destroyed when they exit scope, RAII ensures your applications never leak resources.

Let's look at custom destructors and how to implement the RAII design pattern.

Destructors: Cleaning Up the Mess

A destructor is a special member function that is called automatically when an object goes out of scope or is deleted. It has no return type, takes no arguments, and shares the class name prefixed with a tilde ~:

class Simple {
public:
    Simple() {
        // Constructor: Acquire resource here
    }
    ~Simple() {
        // Destructor: Free resource here
    }
};
Custom destructor syntax.

The RAII Pattern: Automatic Housekeeping

Let's see a practical example of RAII. If you open a file using raw system calls and your code throws an exception before you call close, the file handle leaks, locking the file. By wrapping the file handle inside a class constructor and destructor, we guarantee the file is closed automatically when the wrapper object exits scope, even if an exception occurs:

#include <iostream>
#include <fstream>
#include <string>

class SafeFile {
    std::ofstream fileStream;
public:
    // Constructor: Acquires the resource (opens file)
    SafeFile(const std::string& filename) : fileStream{filename} {
        if (fileStream.is_open()) {
            std::cout << "Resource acquired: File opened.\n";
        }
    }

    // Destructor: Releases the resource automatically when scope exits!
    ~SafeFile() {
        if (fileStream.is_open()) {
            fileStream.close();
            std::cout << "Resource released: File closed.\n";
        }
    }

    void writeData(const std::string& text) {
        fileStream << text << '\n';
    }
};

int main() {
    {
        SafeFile writer{"log.txt"};
        writer.writeData("Hello systems programming!");
    } // writer exits scope here! ~SafeFile is invoked automatically, closing the file.
    return 0;
}
Implementing a safe file manager wrapper with RAII.

* The Concierge Metaphor: Think of RAII as hiring a highly professional hotel concierge. The moment you check out of the room (the object exits scope), the concierge automatically sweeps the floors, locks the safe, cleans the bathroom, and turns off the lights. You do not have to worry about cleaning up after yourself; it is guaranteed to happen.

Finished reading this lesson?