我有一个班级:
class A
{
public:
void foo(void)
{
// equals to syntactically incorrect (&this == nullptr)
if (*(void**)this == nullptr)
return;
...
}
};
我这样用:
A * a = new A;
...
delete a;
...
a->foo();
为什么发布版本的条件仅为true
?如果我切换到 debug 版本,我通常会得到类似0xFEEFEEFE的内容。
修改
好的伙计们。你说的是绝对正确的,我知道。 未定义的行为是标准未指定的行为。 这是每个平台以自己的方式实现(但实现)。
这个问题的目的是了解它是如何在Windows中实现的。此代码始终正常工作('始终正确'表示:在所有版本的Windows上(以xp开头),任何编译器调用该方法,并且该语句为真))。在我的情况下,我想知道如果在Windows 中删除对象,通常会发生什么。
P.S。 我应该在wasm.ru中问过这个问题。遗憾。
答案 0 :(得分:5)
为什么这一切都是真的?未指定删除后指针的值是什么。删除后,不需要实现将指针设置为null。除非你已经在疯狂的城镇,否则真的this
永远不会为空。
编辑:OP显示更多代码后:
A * a = new A;
...
delete a;
...
a->foo();
是的,那条线a->foo();
?这是获得未定义行为的最可靠方式。
答案 1 :(得分:3)
您假设delete会将nullptr放入保存指针被删除的变量中。事实并非如此,delete
并没有这样做。
为什么条件适用于发布版本?如果我切换到调试版本,我通常会得到像0xFEEFEEFE。
当您在Windows下调用delete a;
时,CRT库会将指针下的内存标记为已释放。在调试模式下,它还会在此内存区域中放入0xFEEFEEFE值,这意味着freefree。这使得在调试时使用释放内存时更容易找到。在发布模式下,删除后CRT不会显示此值。
if(*(void **)this == nullptr)
在这种情况下,this
指针被声明为class-type * this
,因此将它转换为(void **)是完全错误的。
A-> FOO();
这是错误的,删除后你不应该使用 - 它会导致UB