Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么删除后(&this!=nullptr)?_C++_Oop_Debugging - Fatal编程技术网

C++ 为什么删除后(&this!=nullptr)?

C++ 为什么删除后(&this!=nullptr)?,c++,oop,debugging,C++,Oop,Debugging,我有一门课: class A { public: void foo(void) { // equals to syntactically incorrect (&this == nullptr) if (*(void**)this == nullptr) return; ... } }; 我是这样使用它的: A * a = new A; ... delete a; ... a->f

我有一门课:

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();
为什么该条件仅适用于发布版本?如果切换到调试版本,通常会得到类似0xfeefe的结果

编辑

好的,伙计们。你说的绝对正确,我知道。 未定义的行为是标准中未指定的行为。 这是每个平台实现的,但以自己的方式实现

这个问题的目的是了解它是如何在Windows中实现的。此代码始终正常工作“始终正常”意味着:在所有版本的Windows上,从xp开始,任何编译器都会调用该方法,并且该语句为true。在我的例子中,我想知道如果在Windows中删除对象通常会发生什么

附言。
我应该用wasm.ru问这个问题。对不起。

为什么这是真的?未指定删除指针后指针的值。删除指针后,实现不需要将指针设置为null。事实上,除非你已经在疯狂的小镇上,否则这永远不会是空的

编辑:OP后显示更多代码:

A * a = new A;
...

delete a;
...

a->foo();

是的,那行a->foo;?这是获得未定义行为的最可靠的方法。

您假设delete会将nullptr放入保存被删除指针的变量中。这不是真的,delete不是这样做的

为什么该条件仅适用于发布版本?如果切换到调试版本,通常会得到类似0xfeefe的结果

当你调用删除一个;在Windows下,CRT库将指针下的内存标记为已释放。在调试模式下,它还将0xfeefefee值放入该内存区域,这意味着空闲。这使得在调试过程中,当使用释放的内存时,更容易查找案例。在释放模式下,CRT在删除后未输入此值

如果*void**this==nullptr

在本例中,该指针被声明为类类型*this,因此将其强制转换为void**完全是错误的

a->foo


这是错误的,删除后你不应该使用a-这会导致UB

未定义的行为未定义,不要做导致它的事情。不,*void**这不等于&this。a->foo调用未定义的行为,所以任何事情都可能发生。与此相同的主题正在发挥作用。唯一正确的方法是按原样测试它,不是在一个打字框后取消引用,但即使如此,它也只是稍微有帮助,如果我参与了一个项目,我们实际上是出于一个除了几年前放支票的人之外没有人知道的原因,但也没有人有动机删除支票的话。该标准明确规定,如果你学究气十足,在删除它后,包括查看它,你可能不会对它做任何事情!因此,光是会员电话就已经深入到了UB的土地上,而此后发生的任何检查都只是一次偶然的机会……为什么要投否决票?这是正确的答案。它甚至警告人们不要去疯狂小镇。为了补充这个正确的答案,取消将其作为有效性检查的引用也是调用UB的可靠方法。请注意,*void**不仅将其类型转换为指向void指针的指针,还取消对该指针的引用。如果这是有效的,那么这就是废话,如果不是,那么更多的废话作为安全检查。过度使用安全检查通常会导致更慢、更不安全的代码-真实的故事。好吧,那这又如何呢。如果CRT没有输入值0xFEEFEFFF,那么它可能会输入零?为什么调用a->foo做它所做的事情?为什么内存中的foo代码仍然引用到已删除的对象?或者它可能没有被引用。但是为什么调用a->foo会将我变成foo的主体呢?它不会将0xFEEEFEEE或NULL放入a变量中,而是放入a指向的内存中。您可以这样理解:这主要是作为一个隐藏的方法参数实现的,所以在您的foo方法调用中,它将等于a中的地址,即使它是一个悬空指针。因此,调用将成功,您将看到这是与删除之前相同的指针,即使这是无效指针,但您的foo方法将处理保留在已释放内存区域中的数据。。。。。。。此内存区域可能与长时间调用delete之前相同。但其他一些分配可能会利用这个区域,并在那里放置一些新数据。这是UB,这是应该避免的。在那个帖子里,你建议我说这不是一个变量。这是一种表达。那么,有没有这张桌子?CRT对一个物体的这一点“跟踪”多长时间?我试着删除我的对象,分配很多东西,写它,发布它;但同样,如果我把它称为deleted a->foo,那么这个值是零。我知道a所指的记忆已经改变了。但是这是从哪里获取的,并传递到foo?@JohnSmith这更像是:a->fooa;,所以它是作为参数传递的,这也意味着它不会与类实例一起存储。没有这张桌子。CRT不会显式地跟踪这些指针,在您的例子中,这是针对yo的 ur类实例是一个变量,它的生命周期在main结束时结束。我有一个零这个-我试过了,在调试和发布时,这个在删除后永远不会是零-至少在VS2015下。