调用析构函数后访问对象

Bar*_*lad 2 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();
};
Run Code Online (Sandbox Code Playgroud)

和析构函数:

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;
}
Run Code Online (Sandbox Code Playgroud)

在源码.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!
Run Code Online (Sandbox Code Playgroud)

输出是:

4 3 7

我预计会出现错误:

标识符“q”未定义

for*_*818 5

从字面上看//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
Run Code Online (Sandbox Code Playgroud)

您似乎对堆栈分配对象的生命周期有误解。堆栈对象在超出范围时会自动销毁。在示例中, 的范围q以 结尾}

自己调用析构函数几乎总是错误的(我恰好遇到过一种情况,可以显式调用析构函数)。为什么?考虑一下:

{
    Queue q;
    q.~Queue();   // DONT DO THIS !
}
Run Code Online (Sandbox Code Playgroud)

您调用了析构函数,但是当它超出范围时,它会再次被销毁,并且您将收到令人讨厌的运行时错误。

您在代码中执行的操作:

Queue q;
q.~Queue();
q.print();
Run Code Online (Sandbox Code Playgroud)

未定义的行为

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

我怎样才能删除它(让它消失)?

你无法让它“消失”。当对象被销毁时,内存中的位和字节不会被删除。那将是非常低效的。事实上,我认为 Cfree有一个更好且更容易混淆的名称。内存被释放以供以后使用,它不会被擦除,以致无法读取之前的内容。

为了进一步阅读,我建议您参考这个稍微不同但相关的问题的详尽答案:局部变量的内存可以在其范围之外访问吗?

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

TL;DR:如果你想清除Queue然后写:

q.clear();
q.print(); // prints an empty queue!
Run Code Online (Sandbox Code Playgroud)

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