【问题标题】:delete this ? what does it do?删除这个?它有什么作用?
【发布时间】:2011-11-05 10:11:22
【问题描述】:

鉴于以下情况:

#include <iostream>
using namespace std;

class A
{
public:
    void func() {delete this;}
    A() : x(5) {cout << "ctor A" << endl;}
    ~A() {cout << "dtor A" << endl;}
    int x;
};

int main() {
    A a;
    cout << "The X value: " << a.x << endl;
    a.func();  // calling 'delete this' ->going to the dtor #1
    cout << "The X value: " << a.x << endl;
    return 0;  
}

输出是:

ctor A
The X value: 5
dtor A
The X value: 5
dtor A

delete this; 有什么严重的影响吗?

【问题讨论】:

  • 试图删除尚未通过 new 分配的内容:错误。删除后尝试访问某些内容:错误。
  • 我同意你的观点,我只想表明,即使在第一次删除调用之后,该对象仍然保留“x”的值……只是对我来说有点奇怪。
  • “x”值可能是 5,也可能不是。并且应用程序可能会或可能不会崩溃。看这个经典的解释:stackoverflow.com/questions/6441218/…
  • 我很好奇:是什么促使你尝试这个?
  • 我也很好奇。我知道这是一个禁忌!只是想知道为什么。

标签: c++ destructor delete-operator self-destruction


【解决方案1】:

你不应该这样做。这是不好的编程习惯。使用new的对象应该是使用delete的对象。否则你会陷入混乱并最终导致内存泄漏等。

【讨论】:

  • 对象不做任何事情。它们只是存在。函数做事。
【解决方案2】:

在这种情况下(您没有通过 new 分配 A 对象),您正在调用未定义的行为。未定义的行为通常是一件非常非常糟糕的事情。基本上,任何事情都有可能发生。

可以编写“删除这个;”的代码。不过会好的。但我不记得曾经这样做过。尽量避免它。通过将此责任委托给其他对象(例如,智能指针),尽量避免完全手动调用 delete(无论您是否使用了 new)。

【讨论】:

    【解决方案3】:

    我会回顾一下您在堆栈分配的对象上调用delete,并检查delete this 的一般用法。

    有一种思想流派说“这不是一个好主意”。但是,我已经看到它在引用计数对象的实现中多次使用。

    COM 中,框架要求所有对象都由工厂方法创建,然后通过调用“Release”再次释放。

      class MyRefCountedObject : public IUnknown
      {
          private:
               // Making the constructor and destructor private
               // so that the object can only be allocated as a pointer
    
               MyRefCountedObject() {}
    
               ~MyRefCountedObject() {}
    
               MyRefCountedObject(const MyRefCountedObject& mrco) {}
    
                int _refCount;
          public:
               static MyRefCountedObject* CreateInstance()
               {
                    MyRefCountedObject* pObject = new MyRefCountedObject();
                    pObject->_refCount = 1;
                    return pObject;
               }
    
               void Release()
               {
                    if(--_refCount == 0)
                    {
                        delete this;
                    }
               };
               void AddRef()
               {
                   ++_refCount;
               }
      }
    

    注意 - 这不是一个完整的实现,只是给出一个逻辑概念。 但是,通过将构造函数设为私有,我可以确保它只会在堆上分配。

    【讨论】:

      【解决方案4】:

      delete 操作符调用对象的析构函数然后释放对象使用的底层内存。内存必须已由new 运算符分配。在delete this 中,删除的对象就是当前对象。构造没有什么特别之处,就是普通的 C++。

      在您的示例中,内存来自堆栈,因此您进入了未定义行为的领域(因为您在未通过 new 运算符分配的对象上调用 delete 运算符)。

      调用delete this 通常被认为是糟糕的设计,因为对象不应该对自己的生命周期负责。通常认为最佳做法是让对象的创建者对其销毁负责。

      但是,有一种情况我个人认为它非常有用。当您通过发送消息进行线程通信时,就会发生这种情况。在这种情况下,如果消息负责它自己的生命周期,那么它实际上比让原始线程负责它更安全、更容易编写。

      【讨论】:

      • 知道了。那么为什么“a.x”在第一次删除调用后仍然保持值“5”?为什么程序没有崩溃?
      • 好吧,当您遇到未定义的行为时,任何事情都可能发生,即使程序按照您的预期工作。由于您没有析构函数,因此值没有更改,并且由于对象在堆栈上,因此该对象仍然可以访问。但是,您可能损坏了分配器。但是没有什么可以保证的,这是UB的根源。
      【解决方案5】:

      C++ FAQ Lite: "Is it legal (and moral) for a member function to say 'delete this'?"

      也就是说,您应该很少在适当组织的代码中使用它。

      【讨论】:

        猜你喜欢
        • 2010-10-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-23
        • 2022-11-10
        • 1970-01-01
        • 2012-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多