Какие классы и идиомы в C++ используют паттерн RAII?

«Какие классы и идиомы в C++ используют паттерн RAII?» — вопрос из категории Управление памятью, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

RAII (Resource Acquisition Is Initialization) — это фундаментальная идиома C++, где захват ресурса (память, файл, мьютекс) неразрывно связан с инициализацией объекта, а освобождение — с его разрушением. Это гарантирует безопасность при исключениях.

Ключевые примеры использования RAII в стандартной библиотеке C++:

  1. Управление памятью: Умные указатели std::unique_ptr, std::shared_ptr, std::vector, std::string. Память выделяется в конструкторе и освобождается в деструкторе.

    void processFile() {
        auto buffer = std::make_unique<char[]>(1024); // Память выделена
        // ... работа с buffer
        if (some_error) throw std::runtime_error("Oops");
    } // Деструктор unique_ptr ВСЕГДА вызовет delete[], даже при исключении
  2. Управление файлами: Потоки (std::fstream, std::ifstream, std::ofstream)

    {
        std::ofstream out("data.bin", std::ios::binary); // Файл открыт
        out.write(data, size);
    } // Файл автоматически закрывается в деструкторе out
  3. Управление блокировками: Мьютексы (std::lock_guard, std::unique_lock)

    std::mutex critical_mutex;
    void threadSafeFunction() {
        std::lock_guard<std::mutex> lock(critical_mutex); // Захват мьютекса
        // Критическая секция защищена
    } // Мьютекс гарантированно освобождается при выходе из функции
  4. Прочие ресурсы: Соединения с БД (в библиотеках вроде SOCI), дескрипторы сокетов (в обёртках), графические ресурсы (OpenGL/Vulkan object wrappers).

Преимущество: Код становится безопасным от утечек и более чистым, так как не требует явных вызовов delete, close(), unlock().