В какой ситуации деструктор С++ не будет вызван?

В С++ мы любим делать что-то в деструкторе. Но в какой ситуации деструктор не будет вызван?

Примеры в следующих случаях:

  • exit() вызов в потоке
  • необработанные исключения и выход
  • TerminateProcess() (в Windows)
  • теплый/холодный компьютер перезагрузки.
  • внезапный выход из компьютера...

Ответ 1

Это один случай, который должен знать каждый программист на С++:

#include <stdio.h>

class EmbeddedObject {
   private:
      char *pBytes;
   public:
      EmbeddedObject() {
         pBytes = new char[1000];
      }
     ~EmbeddedObject() {
         printf("EmbeddedObject::~EmbeddedObject()\n");
         delete [] pBytes;
      }
};

class Base {
  public:
    ~Base(){
       printf("Base::~Base()\n");
  }
};

class Derived : public Base {
   private:
      EmbeddedObject emb;
   public:
      ~Derived() {
         printf("Derived::~Derived()\n");
      }
};


int main (int argc, const char * argv[])
{
  Derived *pd = new Derived();
  // later for some good reason, point to it using Base pointer
  Base* pb = pd;
  delete pb; 
}

~Base() будет вызываться, но ~Derived() не будет. Это означает, что код в ~Derived() не выполняется. Возможно, что-то важное. Также он должен был автоматически вызываться деструктор EmbeddedObject, но это не так. Поэтому EmbeddedObject не получает возможности освобождать свои динамически распределенные данные. Это вызывает утечку памяти.

Решение, сделайте деструктор в классе Base virtual:

class Base {
  public:
    virtual ~Base() {
    }   
};

Приведение этого изменения в указанную выше программу означает, что все деструкторы будут вызываться в этом другом: Derived::~Derived(), EmbeddedObject::~EmbeddedObject(), Base::~Base()

Прочитайте деструкторы в целом. Такие проблемы, скорее всего, будут для вас чем-то серьезным, чем другие сценарии, которые вы упомянули. Например, в случае отключения питания все ставки для безопасной очистки обычно отключены!

В С++ у нас есть хороший контроль над выполнением вызова деструкторов в том порядке, в котором мы хотим, чтобы они произошли, что является хорошей новостью. Однако в программах, которые вы пишете, существует вероятность того, что ваши объекты будут пропущены, а не удалены вообще, если вы недостаточно осторожны.

Ответ 2

Деструкторы не будут вызываться для объектов за пределами бесконечного цикла.

Ответ 3

Если вы создадите объект с новым размещением, деструктор для этого объекта не будет вызываться автоматически.

Ответ 4

Appart из очевидных вещей, упомянутых, например, exit(), kill signal, power failure и т.д.

Существуют очень распространенные ошибки программирования, которые препятствовали бы вызову деструктора.

1) Создается динамический массив объектов с object* x = new object[n], но освобожден с помощью delete x вместо delete[] x;

2) Вместо вызова delete() на объект, который вы вызываете free(), вместо этого. Хотя память обычно освобождается, деструктор не будет вызываться.

3) Предположим, что у вас есть иерархия объектов, которые должны были объявить виртуальные деструкторы, но по какой-то причине этого не произошло. Если один из экземпляров подкласса отличен к другому типу в иерархии, а затем удаляется, он может не вызывать все деструкторы.

Ответ 5

Выбросить исключение в другом деструкторе, вызываемом из-за созданного исключения.