#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;
}
- Память, выделенная для p1, освобождается с помощью
delete p4
. Итак, вызывается деструктор delete p3
вызывает следующий деструктор.- 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.