首先要说我是西班牙语,我的英语真的很不好,我使用了一个翻译,并为自己的文盲而道歉:)
我已经好几年没有玩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
谢谢
答案 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 }})。