“删除此项;”期间发生了什么陈述

What is happening during `delete this;` statement?

本文关键字:发生了 什么 陈述 删除 删除此项      更新时间:2023-10-16

请考虑以下代码:

class foo
{
public:
    foo(){}
    ~foo(){}
    void done() { delete this;}
private:
    int x;
};

以下两个选项中发生了什么(有效吗?):

选项1:

void main()
{
   foo* a = new foo();
   a->done();
   delete a;
}

选项2:

void main()
{
   foo a;
   a.done();
}

选项1中的第二个delete a;语句会导致异常或堆损坏吗?

option2会导致异常或堆损坏吗?

delete this;是允许的,它会删除对象。

您的两个代码片段都有未定义的行为——在第一种情况下,删除已经删除的对象,在第二种情况下删除具有自动存储持续时间的对象。

由于行为是未定义的,所以标准没有说明它们是否会导致异常或堆损坏。对于不同的实现,它可能是任意一种,也可能不是,也可能两者都是,而且每次运行代码时,它可能相同,也可能不相同。

两者都会导致错误。

第一个指针被删除两次,第二个delete导致错误,而第二个指针被分配在堆栈上,不能被隐式删除(第一次调用析构函数导致错误)。

这个问题已经得到了回答,但我要补充一点,如果你的类确实调用了delete This,那么你也应该将析构函数设为私有的。

这样可以确保只有类可以删除自己。

如果您在上面将析构函数设为私有的,那么两个代码示例都将无法编译。

调用delete this是个坏主意。无论谁呼叫new,都应该呼叫delete。因此出现了其他答复中强调的问题。

此外,在构造对象数组时,可能会出现内存泄漏/未定义行为。

两者都会导致错误,您需要的是:

void main()
{
   foo* a = new foo();
   a->done();
}

编译器将扩展到下面这样的内容,我希望这能减少删除"this"的混乱。

void __foo_done(foo* this)
{
   delete this;
}
void main()
{
   foo* a = new foo();
   __foo_done(a);
}

另请参阅,成员函数说删除这个是否合法(和道德)?

对于释放内存的上下文,我会非常谨慎。虽然调用"delete this;"将尝试释放与类结构相关的内存,但该操作无法推断原始内存分配的上下文,即,是否从堆或堆栈中分配。我的建议是重新编写代码,以便从外部上下文调用deallocation操作。请注意,这与释放类内部的结构不同,在这种情况下,请使用析构函数。

在这两种情况下,堆都会损坏。当然,你不能在选项2中使用"->"如果左边的值(在本例中为"a")不是指针,选项2中的正确形式将是a.done();但是,是的,如果你试图删除1)已经删除的内容,或者2)本地变量,你应该会得到堆损坏。

调用"delete this"在技术上是有效的,可以释放内存。

编辑我很好奇,实际上试过这个:

class foo 
{
public: 
    foo(){} 
    ~foo(){} 
    void done() { delete this; } 
    void test() { x = 2; }
    int getx() { return x; }
private: 
    int x; 
} ;

int main(int argc, char* argv[])
{
    foo *a = new foo();
    a->done();
    a->test();
    int x = a->getx();
    printf("%in", x);
    return x;
}

printf的调用将成功,并且x将保持值2