0

我注意到我的 C++ 代码中有一些非常奇怪的东西。

class A
{
    public:
    void doIt(){cout<<"hello"<<endl;}
};
int main() {
    A* a=new A();
    A* b=a;
    delete a;
    b->doIt();
    return 0;
}

我认为这delete会从堆中删除内存并且b->doIt()会失败。但是在运行这段代码时它可以工作,甚至打印“hello”。

为什么?

4

2 回答 2

4

我认为删除会从堆中删除内存

你可以“擦除”记忆的唯一方法是用锤子。

内存被标记为“未使用”并且对象在语义上被销毁。

并且b->doIt()会失败

为什么?

没有适当的机制可以为您做到这一点,在一般情况下也没有机制。

不对不存在的对象调用函数是您的责任。

实际上,它不会在这里崩溃,因为doIt实际上没有任何尝试访问对象的内存。请记住,函数并​​不存储在对象“中”——它是您程序的一部分,并且您的程序仍然存在。

即使doIt访问和/或改变了对象的状态,只要该内存仍在活动页面中,您可能仍然不会崩溃。这正是为什么未定义的行为被定义为不可预测的原因。

避免。


于 2016-02-18T11:56:50.947 回答
1

这很可能是因为doIt方法不使用 A 类的任何内部状态。因此,编译器可能会将其优化为静态方法,并在静态类上下文中调用该调用。指针悬空的事实不会阻止该方法运行。

但是,这是未定义的行为,更严格的编译器实际上可能会生成确实失败的代码。

于 2016-02-18T11:45:24.373 回答