33

在我最初的基本测试中,这样做是完全安全的。但是,让我感到震惊的是,稍后尝试在sthis的函数中进行操作可能是运行时错误。这是真的吗?通常安全吗?还是只有某些情况下它是安全的?deletethisdelete this

4

10 回答 10

46

delete this是合法的,并且可以满足您的期望:它调用您的类的析构函数并释放底层内存。返回后delete this,您的this指针值不会改变,因此它现在是一个不应取消引用的悬空指针。这包括使用类的成员变量进行隐式取消引用。

通常在引用计数类中发现,当引用计数减为 0 时,DecrementRefCount()// Release()whatever 成员函数调用delete this.

delete this由于许多原因,通常被认为是非常糟糕的形式。之后很容易意外访问成员变量delete this。调用者代码可能没有意识到您的对象已自毁。

此外,delete this您的代码可能没有针对对象所有权(谁分配和谁删除)的对称策略,这是一种“代码味道”。一个对象不能用 来分配自己new,所以调用delete this意味着 A 类正在分配一个对象,但 B 类稍后会释放它[self]。

于 2009-02-15T02:36:31.653 回答
16

只要它本质上是方法中的最后一个操作,删除“this”是安全的。事实上,有几个专业级别的 API 会这样做(请参阅 ATL 的 CComObject 实现以获取示例)。

唯一的危险是在调用“delete this”之后尝试访问任何其他成员数据。这当然是不安全的。

于 2009-02-15T02:28:54.680 回答
14

但不要在析构函数中这样做!

于 2009-02-15T02:41:46.617 回答
13

正如其他人已经提到的那样,删除它是完全合法的。由于尚未提及的另一个原因,这是有风险的 - 您假设对象已在堆上分配。这可能很难保证,尽管在引用计数实现的情况下通常不是问题。

于 2009-02-15T02:41:37.273 回答
6

正如其他人所说, delete 这是一个有效的习惯用法,但为了安全起见,您必须确保该对象永远不会在堆栈上实例化。

一种方法是使构造函数和析构函数都是私有的,并通过类工厂函数强制创建对象,该函数在堆上创建对象并返回指向它的指针。类工厂可以是静态成员函数或友元函数。然后可以通过对执行“删除此”的对象的 Delete() 方法进行清理。COM 对象基本上以这种方式工作,除了它们是引用计数的,当引用计数减为零时会发生“删除这个”。

于 2009-02-15T02:41:43.747 回答
3

是的。应该没问题。“这”只是一个指针。任何指针都可以删除。有关如何删除对象的信息包含在堆记录中。这就是 IUnknown::Release() 通常在 COM 对象中实现的方式。

于 2009-02-15T02:28:09.393 回答
3

当您有要删除的对象的子类时,删除这可能会导致问题。请记住,构建从上到下开始,删除从下到上开始。因此,如果删除它位于层次结构的中间,您基本上会丢失该特定类下的所有对象。

当你实现一个引用计数的对象时,delete 非常方便,COM 类就是一个例子。

于 2009-02-15T02:38:59.523 回答
2

阅读类似的讨论。您的理解是正确的,因为它确实有效,是必需的,并且可能很危险,因为您之后无法访问它。

于 2009-02-15T02:30:53.273 回答
2

合法 是
安全 否

于 2009-02-15T06:46:10.977 回答
-2

如果您是从基类继承并在基类函数中给出了 delete this,则使用派生类指针将导致崩溃。例如:

class Base
{

    virtual void Release()
    {
        delete this;
    }

}

class Derived : public Base
{

    void Foo()
    {
        ...
    }

}

main()
{

    Base *ptrDerived = new Derived();
    ptrDerived->release();
    ptrDerived->Foo() //Crash

}
于 2016-02-04T09:24:17.640 回答