C ++自定义删除运算符不能很好地工作吗?

时间:2018-08-29 21:07:53

标签: c++ virtual delete-operator

首先要说我是西班牙语,我的英语真的很不好,我使用了一个翻译,并为自己的文盲而道歉:)


我已经好几年没有玩c ++了,我已经忘记了很多东西,以至于我的疑惑或可能的失败确实是该语言的基础。

我写了一个小代码来测试带有虚拟析构函数的c ++中delete运算符的开销,我发现它仅在第一次调用delete时才能正常工作。

代码在这里(该页面允许您在线编写并执行代码,我已经在Visual Studio和gcc中对其进行了测试,并且完全相同):https://onlinegdb.com/SkiI1dNDQ

有人可以告诉我为什么会这样吗?只有第一次工作良好,第二次却进展不佳

我也在这里放置了代码,并给出了结果:

#include <stdio.h>
class Base
{
public:
    virtual ~Base() { printf("~Base\r\n"); }
    void operator delete(void *m) { printf("delete Base\r\n"); }
};
class Derived : public Base
{
public:
    Derived() { x = 1; }
    ~Derived() { printf("~Derived\r\n"); }
    void operator delete(void *m) { printf("delete Derived\r\n"); }
    int x;
};

int main()
{
    Derived *derived = new Derived();
    printf("1) delete derived (%i)\r\n", ((Derived*)derived)->x);
    delete derived;
    printf("2) delete derived (%i)\r\n", ((Derived*)derived)->x);
    delete derived;
    return 0;
}

结果:

1) delete derived (1)
~Derived
~Base
delete Derived
2) delete derived (1)
~Base
delete Base

现在,如果我们删除名为“ Base”的“虚拟”类,那么一切都完美无缺,从逻辑上讲,每当我们使用“ Derived”调用删除时(代码已准备就绪,可以删除虚拟且没有任何失败)。要执行它:https://onlinegdb.com/SkXkgdVP7

谢谢

1 个答案:

答案 0 :(得分:5)

Derived *derived = new Derived();
printf("1) delete derived (%i)\r\n", ((Derived*)derived)->x);
delete derived;
printf("2) delete derived (%i)\r\n", ((Derived*)derived)->x);
delete derived;

上面的代码不正确,并且正在调用未定义的行为。您只能删除一次对象。在上面,您(试图)删除同一对象两次。问题在于,在第一次调用delete之后,derived现在是一个悬空指针(即不再指向有效对象),尝试以任何方式取消引用(包括调用{{1 }})。