Время жизни и RAII
Главная идея C++: ресурс освобождается сам
После урока ты сможешь
- Предсказывать, когда объект создаётся и уничтожается
- Писать деструктор, который освобождает ресурс
- Объяснить, почему в C++ нет и не нужен сборщик мусора
Шаг 1 из 6
Когда объект рождается и умирает
У каждого объекта в C++ есть точное время жизни. Локальная переменная создаётся там, где объявлена, и уничтожается на закрывающей фигурной скобке своего блока. Это видно, если написать класс, который сообщает о своём рождении и смерти:
#include <print>
#include <string>
#include <utility>
class Noisy {
public:
explicit Noisy(std::string name) : name_(std::move(name)) {
std::println("+ {}", name_);
}
~Noisy() {
std::println("- {}", name_);
}
private:
std::string name_;
};
int main() {
Noisy a("a");
{
Noisy b("b");
Noisy c("c");
std::println("внутри блока");
} // здесь умирают c, затем b
std::println("после блока");
} // здесь умирает a
Метод ~Noisy() — деструктор: он вызывается автоматически, когда объект уничтожается. Его никогда не вызывают вручную.
Два правила, которые стоит запомнить:
- Объект уничтожается при выходе из своей области видимости, каким бы путём ни произошёл выход: конец блока,
return,break, исключение. - Объекты одной области уничтожаются в обратном порядке создания.
cсоздан последним и умирает первым: то, что создано позже, может зависеть от созданного раньше.
Проверь себя
Что выведет программа?
#include <print>
struct Tag {
char name;
~Tag() { std::print("{}", name); }
};
int main() {
Tag a{'a'};
{
Tag b{'b'};
Tag c{'c'};
}
Tag d{'d'};
std::println("");
}