Краткое объяснение всеми любимой аббревиатуры C++ :)
Как это принято в C++, знание того, что означает аббревиатура, не поможет вам понять концепцию, стоящую за ней. RAII не является исключением. Итак, давайте вместо этого просто предположим, что это означает:
деструкторы-очистка-после-области
Да мелочь это все. Давайте посмотрим на пример:
struct Foo { Foo() { x = new int[10]{42}; } ~Foo() { delete[] x; } int* x; }; void bar() { Foo foo; // constructor called // do stuff with foo } // destructor called
У Foo есть конструктор и деструктор. Конструктор вызывается в начале bar(), а деструктор вызывается автоматически, когда foo выходит из области видимости в конце bar(). Это РАИИ. Это ограниченное управление сроком службы.
Что такое масштаб, спросите вы. Это что-то между { и }, где деструкторы вызываются при достижении }. Деструкторы вызываются в порядке, обратном их конструкторам. Например:
void bar() { Foo foo1; // constructor creates foo1 Foo foo2; // constructor creates foo2 // do stuff with foo1 and foo2 } // destructors are called: First foo2’s and then foo1’s
Еще одна приятная особенность заключается в том, что RAII делает ваш код безопасным для исключений, что означает, что создание исключений не приведет к утечке ресурсов. Возьмите этот пример:
void bar() { Foo foo; // constructor creates foo // do stuff with foo throw std::runtime_error{"error"}; } // we don't get here int main() { try { bar(); } catch (const std::runtime_error& e) { // foo's destructor is called // handle e } }
Исключение (std::runtime_error) генерируется после создания foo, поэтому мы не дойдем до конца области видимости bar(). Но в момент обработки исключения в main() (в начале предложения catch) деструктор все еще вызывается, а ресурсы очищаются. Хороший.
Итак, у вас есть это. RAII — это механизм управления ресурсами на основе областей. Деструктор вызывается в конце области видимости (или при обработке исключения).
Спасибо за прочтение!