Вызов деструктора в C

#c #destructor

#c #деструктор

Вопрос:

Я изучил, что Destructor это вызывается всякий раз, когда объект выходит за пределы области видимости или когда выделенная ему память освобождается с помощью delete оператора.

 #include  <iostream>

using namespace std;

class point
{
   private:
      int x_coord;
      int y_coord;

   public:
      point()
      {
         x_coord = 0;
         y_coord = 0;
      }

      point(int x, int y)
      {
         x_coord = (x > 79 ? 79 : (x < 0 ? 0 : x));
         y_coord = (y > 79 ? 79 : (y < 0 ? 0 : y));
      }

      ~point()
      {
         cout << "Destructor invokedn";
      }

      int getx(void)
      {
         return x_coord;
      }

      int gety(void)
      {
         return y_coord;
      }
};

int main()
{
   point p1;
   point p2(20, 80);

   point *p3 = new point;

   cout << "p1.x =  " << p1.getx() << ": p1.y = " << p1.gety()<< "n";
   cout << "p2.x =  " << p2.getx() << ": p2.y = " << p2.gety()<< "n";
   cout << "p3->x =  " << p3->getx() << ": p3->y = " << p3->gety()<< "n";

   point * p4 = amp;p1;
   delete p4;
   delete p3;

   return 0;

}
 
  1. Память, выделенная для p1, освобождается с помощью delete p4 . Итак, вызывается деструктор
  2. delete p3 вызывает следующий деструктор.
  3. p2 выходит за пределы области видимости, и вызывается следующий деструктор.

Я ожидал, что деструктор будет вызван только 3 раза. Но я вижу, что деструктор вызывается 4 раза. В чем причина этого? Есть ли какая-то ошибка в отношении моего понимания деструкторов

Комментарии:

1. Я не думаю delete p4 , что это правильно.

2. Вы не delete p1 должны использовать его, поскольку он был выделен в стеке.

3. Ваш пример можно было бы значительно сократить, если бы вы удалили все методы, кроме деструктора, полей и кода main() , вызывающего эти методы. Они не имеют отношения к вашему вопросу.

4. Отлично!. Я понял. Спасибо всем 🙂

Ответ №1:

В коде ошибка. Вы не можете delete p1 ( p4 указывает на p1 ), поскольку он не new был создан с. Таким образом, программа вызывает неопределенное поведение.

Что происходит в этом конкретном случае, так это то, что деструктор p1 вызывается дважды: сначала с delete помощью, второй раз, когда p1 выходит за пределы области видимости. Это может быть и что-то другое (другой вероятный результат — сбой).

Ответ №2:

Вы уничтожаете p1 дважды, один раз, когда p1 выходите за пределы области видимости, но также и при вызове delete p4 , который является просто указателем на p1 , а не на отдельный объект. Кстати, уничтожение объекта дважды является неопределенным поведением (как и удаление объекта стека (см. Комментарий)).

Комментарии:

1. Это не UB, потому что объект уничтожается дважды, но это UB, потому что передается адрес, который не new был возвращен delete . p1 является объектом в стеке, а не в свободном хранилище.

Ответ №3:

p1 был выделен в стеке, поэтому, даже если вы вызывали delete p4 , delete будет вызываться для теперь нераспределенного p1 .

Обратите внимание, что освобождение памяти не приводит (обязательно) к ее обнулению. Таким образом, деструктор можно вызвать снова и распечатать сообщение. Или он может взорваться. Вот почему очень важно убедиться, что вы не освобождаете память перед последним использованием.

Ответ №4:

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