Доступ к объекту после вызова деструктора - PullRequest
1 голос
/ 12 апреля 2019

В приведенном ниже коде я вызываю ~ деструктор () явно.Однако объект все еще доступен.Как я могу удалить его (заставить его исчезнуть)?

class Queue {
public:
    node* top = NULL;//points to the top of the queue 
    //methods:
    void enqueue(int data);//adds a node to the queue
    void dequeue();
    //printing 
    void print();
    //destructor 
    ~Queue();
};


/*And the destructor:*/ 
Queue::~Queue() {
    //The destructor deletes all items from HEAP
    //Then sets the top to 0
    while (top != NULL)
        this->dequeue();//dequeue until there are NO more items
    top = 0;
}

/ * В Source.cpp: * /

Queue q;

q.enqueue(1);
q.enqueue(2);
q.enqueue(3);
q.enqueue(4);

q.dequeue();
q.dequeue();
q.print();

q.~Queue();
q.print();//Here I need to have an ERROR!

q.enqueue(7);//Here I need to have an ERROR!
q.print();//Here I need to have an ERROR!

Вывод: 4 3 7 Я ожидаю ошибку:идентификатор "q" не определен

1 Ответ

3 голосов
/ 12 апреля 2019

Буквально //Here I need to have an ERROR!, вот как вы это сделаете:

{
    Queue q;

    q.enqueue(1);
    q.enqueue(2);

    q.dequeue();
    q.print();
}
q.print();        // THIS WILL PRODUCE AN ERROR

Похоже, вы неправильно понимаете время жизни объектов, выделенных из стека.Стековые объекты автоматически уничтожаются при выходе из области видимости.В этом примере область действия q заканчивается на }.

Вызывать деструктор самостоятельно почти всегда неправильно (я сталкивался ровно с одним единственным случаем, когда было нормально вызывать деструктор явно).Зачем?Примите во внимание следующее:

{
    Queue q;
    q.~Queue();   // DONT DO THIS !
}

Вы вызвали деструктор, но когда он выходит из области видимости, он снова уничтожается, и вы получаете неприятные ошибки времени выполнения.

Что вы делаете в своем коде:

Queue q;
q.~Queue();
q.print();

- это неопределенное поведение !

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

Как я могу удалить его (заставить его исчезнуть)?

Вы не можете заставить его "исчезнуть".Когда объект уничтожается, биты и байты в памяти не стираются.Это было бы ужасно неэффективно.На самом деле я думаю, что C free имеет гораздо лучшее и менее запутанное имя.Память освобождается для последующего использования, она не стирается так, чтобы было невозможно прочитать то, что было раньше.

Для дальнейшего чтения я отсылаю вас к этому исчерпывающему ответу на несколько иной, но связанный вопрос: Можно ли получить доступ к памяти локальной переменной за пределами ее области видимости?

Также яПредлагаем вам прочитать о RAII , который основан на автоматическом вызове деструкторов.

TL; DR: Если вы хотите очистить Queue, напишите:

q.clear();
q.print(); // prints an empty queue!

Никогда не вызывайте деструктор стекового объекта!Он будет вызван автоматически.

...