EnglishРусский Map

RAII

title
RAII
type
concept
summary
Resource Acquisition Is Initialization - привязка жизни ресурса к жизни объекта для детерминированного освобождения при выходе из области видимости
tags
cpp, memory-management, language-design
created
2026-05-08
updated
2026-07-29
lang
ru
translation_of
raii
source_updated
2026-07-29
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

RAII - Resource Acquisition Is Initialization ("захват ресурса есть инициализация") - дисциплина привязки времени жизни ресурса к времени жизни объекта. Конструктор захватывает ресурс (память, файловый дескриптор, блокировку, сокет); деструктор его освобождает. Пока объект уничтожается детерминированно, ресурс освобождается столь же детерминированно. Никаких try/finally. Никакой дисциплины парных вызовов в каждом месте использования.

Название вводит в заблуждение настолько, что даже Stroustrup позже назвал его неудачным: важно то, что работает деструктор, а не то, что конструктор выполняет захват. Название "управление ресурсами в пределах области видимости" (scoped resource management) описывает суть честнее. Но аббревиатура прижилась.

Устройство

Тип оборачивает ресурс. Конструктор захватывает; деструктор освобождает; семантика копирования и перемещения делает владение явным на уровне типов. Тот, кто держит объект, владеет ресурсом; когда объект умирает, ресурс освобождается. Деструкторы в C++ срабатывают при выходе из области видимости, при раскрутке стека из-за исключений, при удалении элемента из контейнера и при сбросе умного указателя - единообразно, без участия программиста.

unique_ptr, shared_ptr, lock_guard, fstream, vector и string из стандартной библиотеки - всё это RAII-типы. Как и любой тип в Rust с реализацией Drop: Rust взял RAII за основу и сделал его единственным способом управления памятью.

Почему это работает

Аргумент в stroustrup-memory-leaks чисто практический, а не эстетический: человек способен отслеживать несколько десятков объектов, а не десятки тысяч аллокаций. RAII сводит учёт к минимуму. Как только у ресурса появляется владелец, вопрос кто его освобождает превращается в вопрос кто им владеет, а владение видно прямо в сигнатуре типа. Код с адресной арифметикой не даёт ответа ни на один из этих вопросов; RAII-код по своей конструкции отвечает на оба.

Это применимо не только к памяти. Файловые дескрипторы, мьютексы, транзакции баз данных, ресурсы GPU и счётчики ссылок работают по одной и той же схеме захвата и освобождения. RAII кодирует этот паттерн в системе типов.

Требования к языку

Для RAII необходима детерминированная деструкция - деструкторы, которые вызываются в строго определённых точках (выход из области видимости, удаление из контейнера, сброс умного указателя), а не "когда-нибудь потом, когда заметит GC". Языки с недетерминированными финализаторами (Java, Python, Go) не могут использовать RAII напрямую; они вынуждены полагаться на try-with-resources, блоки with или defer, где программисту каждый раз нужно не забыть явно их вызвать.

Языки со сборкой мусора могут управлять памятью без RAII, потому что память взаимозаменяема - небольшая задержка перед её освобождением ничему не вредит. Но они не могут так же управлять невзаимозаменяемыми ресурсами (дескрипторами файлов, блокировками, сетевыми сокетами), из-за чего в Java появился try-with-resources, а в Python - контекстные менеджеры. RAII - это единообразный ответ C++ и Rust на ту же самую проблему.

Связи

  • stroustrup-memory-leaks - каноническая короткая формулировка RAII как средства защиты от утечек памяти
  • delightful-integration-tests-rust - RAII в применении к Docker-контейнеру: как только у ресурса появляется владелец, инфраструктура для конкретного теста полностью заменяет setup и teardown, а недостающая поддержка фикстур оказывается ненужной
  • simplified-model-of-fil-c - Fil-C добавляет безопасность памяти в C/C++ через GC, потому что в легаси-коде дисциплину RAII обеспечить невозможно
  • pointer-provenance - указатели несут идентичность аллокации; RAII помещает эту идентичность внутрь владеющего типа
  • no-silver-bullet - RAII стал редким примером удара по привнесённой сложности (accidental complexity), сократившим целый класс ошибок на порядок
Sub-pages