Можно ли в деструкторе объекта создавать (порождать) другой объект?

«Можно ли в деструкторе объекта создавать (порождать) другой объект?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Технически — да, но это крайне опасная практика, которой следует избегать. Деструктор — это часть процесса уничтожения объекта, и его основная задача — освобождение ресурсов, а не создание новых сущностей.

Критические риски:

  1. Исключения: Начиная с C++11, деструкторы по умолчанию неявно объявлены как noexcept(true). Если в таком деструкторе будет выброшено исключение (например, при неудачном выделении памяти для нового объекта), программа немедленно завершится через std::terminate().

  2. Утечки памяти: Создание динамического объекта (new) в деструкторе и потеря указателя на него — прямая дорога к утечке.

  3. Нарушение инвариантов и неопределенное поведение: Создание объекта может иметь побочные эффекты (изменение глобального состояния, блокировка мьютекса), которые нарушают ожидания от фазы разрушения.

Пример проблемного кода:

class Logger {
    static std::vector<std::string>* globalLog;
public:
    ~Logger() noexcept(false) { // Опасно снимать noexcept!
        // Попытка создать объект в деструкторе.
        if (!globalLog) {
            globalLog = new std::vector<std::string>(); // (1) Потенциальная утечка
        }
        globalLog->push_back("Logger destroyed"); // (2) Может выбросить std::bad_alloc
    }
};
// Если push_back выбросит исключение, а деструктор noexcept(true) -> terminate.

Когда это может быть оправдано? Почти никогда. Единственный условно приемлемый случай — создание объекта с статической продолжительностью хранения (static), время жизни которого привязано ко всей программе, но и это часто признак плохого дизайна.

Правильная альтернатива: Логика, которая должна выполняться «после» разрушения объекта, должна быть вынесена в отдельный метод (например, shutdown(), finalize()), который вызывается явно до деструктора. Деструктор должен быть простым и надежным.