RAII
Resourse Acquisition Is Initialization
Альтернативные названия
CADR (Constructor Acquires, Destructor Releases)
SBRM (Scope-Bound Resourse Management)
Назначение
Resource Acquisition Is Initialization (RAII) – программная идиома, смысл которой заключается в том, чтобы с помощью тех или иных программных механизмов получение некоторого ресурса неразрывно совмещалось с инициализацией, а освобождение – с уничтожением объекта.
Решаемые задачи
необходимость освобождения ресурсов: например памяти или дескрипторов ресурсов
гарантированное освобождение ресурсов при выходе из области видимости
позволяет избежать потери данных при освобождении ресурсов
Общая реализация на С++
В приведенном примере класс File использует идиому RAII для открытия файла в конструкторе и закрытия файла в деструкторе. Это гарантирует, что если возникнет исключительная ситуация, файл будет закрыт корректно, а данные не будут утеряны.
#include <cstdio>
#include <exception>
#include <string>class CannotOpenFileException {};class File
{
private:
std::FILE* f; // файловый дескриптор, который мы оборачиваем
public:
File(const std::string& name)
{
if (f = std::fopen(name.c_str(), "r"); f == nullptr)
{
throw CannotOpenFileException();
}
}
File(const File&) = delete;
File& operator = (const File&) = delete;
// Конструктор перемещения
File(File&& other) noexcept // File&& — ссылка на временный объект
{
f = other.f;
other.f = nullptr; // забираем владение дескриптором у временного объекта other
}
// Оператор присваивания с семантикой перемещения
File& operator = (File&& other) noexcept
{
if (f != nullptr && f != other.f)
{
std::fclose(f); // закрываем файл у текущего объекта
}
f = other.f; // забираем владение у временного объекта other
other.f = nullptr;
return *this;
}
~File() noexcept
{
if (f != nullptr)
{
std::fclose(f);
}
}
std::string Read() const
{
...
}
};int main()
{
try
{
File file("input.txt");
auto str = file.Read();
// ...
}
catch (const CannotOpenFileException&)
{
std::cout << "File open failure!\n";
}
}RAII в стандартной библиотеке
Некоторые примеры применения:
std::unique_ptr и std::shared_ptr - умные указатели, которые используют идиому RAII для автоматического освобождения памяти в деструкторе объекта.
std::ifstream и std::ofstream - классы, которые используют идиому RAII для автоматического закрытия файловых потоков в деструкторе объекта.
std::lock_guard и std::unique_lock - классы, которые используют идиому RAII для автоматического освобождения блокировок при выходе из области видимости объекта.
std::thread - класс, который использует идиому RAII для автоматического завершения потока при выходе из области видимости объекта.
Last updated
Was this helpful?