20

我只是在读这篇文章,希望得到人们的建议:

问:应该delete this;从成员方法中调用吗?

4

12 回答 12

33

通常这是一个坏主意,但它有时很有用。

只要你delete后不使用任何成员变量是绝对安全的,并且只要调用该方法的客户端理解它可能会删除该对象。

当你的类使用引用计数时,这很有用的一个很好的例子:

void Ref() {
  m_References++;
}

void Deref() {
  m_References--;
  if (m_References == 0) {
    delete this;
  }
}
于 2009-12-07T18:26:49.563 回答
12

我认为这里真的有2个问题

可以从成员方法中有效调用删除它吗?

是的。只要您对使用非常小心,这是合法的。

应该在成员方法中使用 delete this 吗?

在非常特殊的情况下,这是必要的。例如,某些类型的智能指针使用该delete this模式来终止指针。例子:CComPtr<>风格。

但是,除了智能指针之外,除非您有充分的理由这样做,否则应该避免使用它。即便如此,我也会仔细重新考虑我的方案,看看是否有办法绕过它。

于 2009-12-07T18:27:06.630 回答
11

是的,你可以,这里很好地解释了何时以及为什么

于 2009-12-07T18:29:02.820 回答
5

是的,有一些情况很常见。

参考计数:

void release() 
{
  cnt--;
  if (cnt == 0) 
    delete this;
}

图形用户界面编程。在某些框架中,当用户关闭一个窗口时,窗口通常会自行删除。

于 2009-12-07T18:28:29.030 回答
5

为反对票做准备。

是否应该:否。
可以吗?技术上:是的:是
不是一个好主意:绝对不是。
有没有有用的情况:当然。如果你是 C++ foo 是非常强大的。但大多数人都不是那么好。所以只有当你有一个团队与你一起工作时,才能进行体面的代码审查。

为什么
一个对象无法知道它是动态分配的(因此需要删除)还是普通对象(因此不能删除),因此它如何决定应该删除的天气。因此,如果一个对象正在删除自己,那么我认为设计存在严重错误。

如果您有一个需要管理的对象,那么您应该编写一个单独的对象来进行管理(因此是智能指针)。让对象做自己擅长的事情,然后将对象的管理分离到另一个对象中。

于 2009-12-07T19:19:58.130 回答
1

这样做并非没有充分的理由。

问题是当你调用delete this一个成员函数时,你正在创造一个令人讨厌的副作用——调用者仍然有一个对你的实例的引用,它现在完全无效。

这可能不是预期的行为,因此很容易导致令人讨厌的错误。

话虽如此,有时这是合适的(我已经看到了一些内存管理方案,在某些库中,您可以在类中显式创建删除自身的方法 - 主要是为了语言互操作性)。不过,总的来说,我认为这是不好的做法。

于 2009-12-07T18:26:49.190 回答
1

一些线程库在线程终止时实现自动销毁时使用它。

void Thread::threadFunc()
{
    doRun();

    if(this->destroyOnExit == true)
        delete this;
}
于 2009-12-07T18:51:29.420 回答
1

这在 MFC 时代经常使用。IIRC 窗口收到的最后一条消息是WM_NCDESTROY,此时您可以调用delete this,当然假设您是某种形式的虐待狂(尽管我认为 MFC 本身有时会这样做。)

于 2009-12-07T19:10:01.303 回答
0

你可以做到,只要它是成员函数中的最后一个元素,并且在返回后你会忘记那个对象曾经存在过......但是,就像那篇文章问的那样......你为什么要这样做?我不知道标准是怎么说的,但它确实给了我一种有趣的感觉:P

我想这有点像你是否曾经使用过 GOTO 语句,我个人有时会使用 GOTO 来清理 C 中的资源,尤其是在特殊情况下。

我想知道共享状态的含义是什么(我知道的模糊陈述):P

于 2009-12-07T18:29:54.967 回答
0

是的。delete this就像所有答案所说的那样,如果您 100% 确定在调用之后不会使用该类的数据。

例如,在一个项目中:

void Test()
MyClass * Someclass = new MyClass;
SomeClass->DoYourThing();
SomeClass->KillYourself();
return;

void MyClass::DoYourThing() { return; }
void MyClass::KillYourself() {delete this;}

非常简单的解释,该项目用作delete this;该类型对象的内存管理的一部分;他们的构造函数将它们添加到正在使用的该类型类的私有列表中,并在它们被销毁时将它们从该列表中删除,然后将它们自己删除(这不在析构函数中)。当程序到达其端点时,该类的任何对象都没有删除自己,那么它们的KillYourself()等价物都会从静态成员函数中调用CleanYourselves()

于 2009-12-07T19:28:15.960 回答
0
  1. delete this不能从非成员函数调用:)
  2. 在您了解其后果之前,这是一个坏主意。
于 2009-12-08T16:18:52.463 回答
0

尽管与此线程没有直接关系,但我想澄清一下。我被问到一个问题,给定一个情况:

int* a = new int ;
int* b = a ;
delete a;

现在下一个语句安全吗?

cout<<*b ;

我的回答:删除 a 后, a指向的位置已被标记为删除,并且在任何时间点都可以将其分配给其他对象。因此,使用b访问值是不安全的,因为它可能在分配给其他对象后被修改。

注意:请不要反对,这只是一个澄清

于 2009-12-30T12:27:30.793 回答