Skip to content

🔒 RAII — The Heart of C++

RAII = Resource Acquisition Is Initialization. Tài nguyên được tự động giải phóng khi object ra khỏi scope.

Analogy: Khóa cửa tự động

┌─────────────────────────────────────────────────────────────────┐
│                    AUTO-LOCKING DOOR ANALOGY                     │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   Manual Lock (new/delete):                                     │
│   ─────────────────────────                                     │
│   1. Mở cửa                                                     │
│   2. Vào phòng                                                  │
│   3. Làm việc                                                   │
│   4. NHỚ khóa cửa khi ra ← Có thể quên!                        │
│                                                                 │
│   Auto-Lock (RAII):                                             │
│   ─────────────────                                             │
│   1. Quẹt thẻ vào phòng (acquire)                              │
│   2. Làm việc                                                   │
│   3. Ra khỏi phòng → Cửa TỰ ĐỘNG khóa                          │
│                                                                 │
│   RAII = Cửa tự động khóa khi bạn rời đi                       │
│   Không thể quên, không thể sai!                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

RAII Principle

cpp
class Resource {
public:
    // Constructor: ACQUIRE resource
    Resource() {
        // Open file, allocate memory, lock mutex, etc.
    }
    
    // Destructor: RELEASE resource (automatic!)
    ~Resource() {
        // Close file, free memory, unlock mutex, etc.
    }
};

void useResource() {
    Resource r;  // Constructor called → resource acquired
    
    // Use resource...
    doSomething(r);
    mayThrowException();  // Even if exception!
    
}  // ← Destructor called → resource released AUTOMATICALLY

Example: File Handle

Without RAII

cpp
void readFile_bad(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) return;
    
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), file)) {
        if (shouldStop(buffer)) {
            // Oops! Forgot to close file!
            return;
        }
        process(buffer);
    }
    
    fclose(file);  // Only reaches here if no early return
}

With RAII

cpp
class FileHandle {
    FILE* file_;
    
public:
    explicit FileHandle(const char* filename) 
        : file_(fopen(filename, "r")) {}
    
    ~FileHandle() {
        if (file_) fclose(file_);  // Auto close!
    }
    
    FILE* get() const { return file_; }
    
    // Prevent copying
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;
};

void readFile_good(const char* filename) {
    FileHandle file(filename);  // Open in constructor
    
    if (!file.get()) return;
    
    char buffer[1024];
    while (fgets(buffer, sizeof(buffer), file.get())) {
        if (shouldStop(buffer)) {
            return;  // ✅ File auto-closed by destructor!
        }
        process(buffer);
    }
}  // ← Destructor closes file automatically

Example: Lock Guard

cpp
#include <mutex>

std::mutex mtx;
int sharedData = 0;

// ❌ Manual lock - dangerous
void increment_bad() {
    mtx.lock();
    
    sharedData++;
    
    if (sharedData > 100) {
        return;  // 💀 Forgot to unlock!
    }
    
    mtx.unlock();
}

// ✅ RAII lock - safe
void increment_good() {
    std::lock_guard<std::mutex> lock(mtx);  // Lock acquired
    
    sharedData++;
    
    if (sharedData > 100) {
        return;  // ✅ Auto unlock on return!
    }
    
}  // ← Auto unlock on scope exit

RAII Guarantees

┌─────────────────────────────────────────────────────────────────┐
│                    RAII GUARANTEES                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   ✅ Normal exit → Destructor called                           │
│   ✅ Return early → Destructor called                          │
│   ✅ Exception thrown → Destructor called                       │
│   ✅ Break/continue → Destructor called                        │
│                                                                 │
│   The ONLY way to skip destructor:                              │
│   ❌ std::terminate()                                           │
│   ❌ std::abort()                                               │
│   ❌ std::_Exit()                                               │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Standard Library RAII Classes

ResourceRAII Wrapper
Memorystd::unique_ptr, std::shared_ptr
Mutexstd::lock_guard, std::unique_lock
Filestd::fstream
Threadstd::jthread (C++20)

Custom RAII Class Template

cpp
template<typename T, typename Deleter>
class ScopeGuard {
    T resource_;
    Deleter deleter_;
    bool released_ = false;
    
public:
    ScopeGuard(T resource, Deleter deleter)
        : resource_(resource), deleter_(deleter) {}
    
    ~ScopeGuard() {
        if (!released_) {
            deleter_(resource_);
        }
    }
    
    T get() const { return resource_; }
    
    void release() { released_ = true; }
    
    // Non-copyable
    ScopeGuard(const ScopeGuard&) = delete;
    ScopeGuard& operator=(const ScopeGuard&) = delete;
};

// Usage
void example() {
    auto* handle = acquireHandle();
    ScopeGuard guard(handle, [](auto* h) { releaseHandle(h); });
    
    // Use handle...
    // Auto-released when guard goes out of scope
}

📚 Tổng kết

AspectDescription
AcquireIn constructor
ReleaseIn destructor (automatic!)
Exception safeYes, always
Never forgetCompiler guarantees cleanup

➡️ Tiếp theo

RAII cho memory = Smart Pointers. Bắt đầu với lựa chọn mặc định:

unique_ptr → — Exclusive ownership.