Защитники области видимости
Запускайте очистку при выходе из области видимости
«Защитники области видимости» — бесплатный урок C++ Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
Что такое защита области видимости
Защита области видимости — это объект RAII, единственная задача которого — выполнить действие очистки при выходе из области видимости, даже при досрочном возврате или исключении.
Какую проблему она решает
Без защиты легко забыть об очистке после досрочного return или throw. Защита области видимости выполняет это действие автоматически.
Стандартная защита области видимости для блокировок
std::lock_guard блокирует мьютекс при создании и разблокирует его при уничтожении — это встроенная защита области видимости для блокировок.
#include <mutex>
std::mutex m;
void critical() {
std::lock_guard<std::mutex> lk(m); // locked
// ... work ...
} // unlocked automaticallyСамостоятельно написанная защита
Вы можете написать защиту, которая хранит функцию и вызывает её в деструкторе.
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
~ScopeGuard() { fn(); }
};
int main() {
ScopeGuard g([] { std::cout << "cleanup\n"; });
std::cout << "work\n";
}Очистка выполняется при досрочном возврате
Поскольку деструктор срабатывает при выходе из области видимости, действие защиты выполняется независимо от того, каким образом завершается функция.
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
~ScopeGuard() { fn(); }
};
void run(bool stop) {
ScopeGuard g([] { std::cout << "always cleaned\n"; });
if (stop) return;
}
int main() { run(true); }Очистка выполняется при исключении
Если исключение раскручивает стек в этой области видимости, деструктор защиты всё равно выполняется и безопасно освобождает ресурс.
Отмена защиты
Иногда очистку нужно пропустить, если операция завершилась успешно. В настоящих защитах предусмотрен метод dismiss(), отключающий это действие.
#include <iostream>
#include <functional>
class ScopeGuard {
std::function<void()> fn;
bool active = true;
public:
ScopeGuard(std::function<void()> f) : fn(std::move(f)) {}
void dismiss() { active = false; }
~ScopeGuard() { if (active) fn(); }
};
int main() {
ScopeGuard g([] { std::cout << "rollback\n"; });
g.dismiss(); // success: no rollback
}Использование для отката
Защиты области видимости особенно полезны в транзакционном коде: зарегистрируйте действие отката, выполните работу, а затем при успехе отмените защиту.
Защиты доступны только для перемещения
Защиту не следует копировать: при копировании действие выполнится дважды. Сделайте защиты доступными только для перемещения или запретите их копирование.
Стандартные и библиотечные помощники
std::scoped_lock защищает несколько мьютексов, а библиотеки вроде GSL предоставляют finally. Во многих кодовых базах есть небольшая утилита ScopeGuard.
Предпочитайте специализированные типы RAII
Если существует специализированный тип RAII для конкретной задачи, например для блокировок, указателей или файловых потоков, предпочитайте его. Используйте универсальную защиту области видимости только для ситуативной очистки, у которой нет естественной оболочки.
Быстрая проверка
Проверьте, насколько хорошо Вы понимаете защиты области видимости.
Итоги
Вы узнали, что защита области видимости автоматически выполняет очистку при выходе из области видимости с помощью RAII. Она обрабатывает досрочные возвраты и исключения, поддерживает откат с помощью dismiss() и должна быть доступна только для перемещения. Предпочитайте специализированные типы RAII, если они существуют.
Часто задаваемые вопросы
Урок «Защитники области видимости» бесплатный?
Да — полный текст урока «Защитники области видимости» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «Защитники области видимости»?
Запускайте очистку при выходе из области видимости Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Защитники области видимости»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Принцип RAII
- Деструкторы и освобождение ресурсов
- Правило трёх/пяти
- Защитники области видимости