调用析构函数后访问对象

时间:2019-04-12 19:27:04

标签: c++ oop destructor

在下面的代码中,我显式调用〜destructor()。但是,该对象仍然可以访问。如何删除(使其消失)?

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 个答案:

答案 0 :(得分:3)

从字面上看,//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();

undefined behaviour

还请注意,删除对象时,调用析构函数并不是全部。当删除堆栈分配的对象时,首先调用其析构函数,然后释放分配的内存。通常,您不想干扰此过程,幸运的是,您很少需要这样做。

  

如何删除(使其消失)?

您不能使其“消失”。销毁对象时,不会擦除内存中的位和字节。那将是非常低效的。实际上,我认为C的free具有更好而更少混淆的名称。内存被释放以供以后使用,它不会被擦除,因此不可能读取之前的内容。

为进一步阅读,我为您介绍了一个详尽的答案,该答案略有不同但相关:Can a local variable's memory be accessed outside its scope?

此外,我建议您阅读有关RAII的内容,该内容依赖于自动调用的析构函数。

TL; DR::如果要清除Queue,请输入:

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

永远不要调用堆栈分配对象的析构函数!它会被自动调用。