我只是在读这篇文章,希望得到人们的建议:
问:应该delete this;
从成员方法中调用吗?
通常这是一个坏主意,但它有时很有用。
只要你delete后不使用任何成员变量是绝对安全的,并且只要调用该方法的客户端理解它可能会删除该对象。
当你的类使用引用计数时,这很有用的一个很好的例子:
void Ref() {
m_References++;
}
void Deref() {
m_References--;
if (m_References == 0) {
delete this;
}
}
我认为这里真的有2个问题
可以从成员方法中有效调用删除它吗?
是的。只要您对使用非常小心,这是合法的。
应该在成员方法中使用 delete this 吗?
在非常特殊的情况下,这是必要的。例如,某些类型的智能指针使用该delete this
模式来终止指针。例子:CComPtr<>
风格。
但是,除了智能指针之外,除非您有充分的理由这样做,否则应该避免使用它。即便如此,我也会仔细重新考虑我的方案,看看是否有办法绕过它。
是的,你可以,这里很好地解释了何时以及为什么
是的,有一些情况很常见。
参考计数:
void release()
{
cnt--;
if (cnt == 0)
delete this;
}
图形用户界面编程。在某些框架中,当用户关闭一个窗口时,窗口通常会自行删除。
为反对票做准备。
是否应该:否。
可以吗?技术上:是的:是
不是一个好主意:绝对不是。
有没有有用的情况:当然。如果你是 C++ foo 是非常强大的。但大多数人都不是那么好。所以只有当你有一个团队与你一起工作时,才能进行体面的代码审查。
为什么:
一个对象无法知道它是动态分配的(因此需要删除)还是普通对象(因此不能删除),因此它如何决定应该删除的天气。因此,如果一个对象正在删除自己,那么我认为设计存在严重错误。
如果您有一个需要管理的对象,那么您应该编写一个单独的对象来进行管理(因此是智能指针)。让对象做自己擅长的事情,然后将对象的管理分离到另一个对象中。
这样做并非没有充分的理由。
问题是当你调用delete this
一个成员函数时,你正在创造一个令人讨厌的副作用——调用者仍然有一个对你的实例的引用,它现在完全无效。
这可能不是预期的行为,因此很容易导致令人讨厌的错误。
话虽如此,有时这是合适的(我已经看到了一些内存管理方案,在某些库中,您可以在类中显式创建删除自身的方法 - 主要是为了语言互操作性)。不过,总的来说,我认为这是不好的做法。
一些线程库在线程终止时实现自动销毁时使用它。
void Thread::threadFunc()
{
doRun();
if(this->destroyOnExit == true)
delete this;
}
这在 MFC 时代经常使用。IIRC 窗口收到的最后一条消息是WM_NCDESTROY
,此时您可以调用delete this
,当然假设您是某种形式的虐待狂(尽管我认为 MFC 本身有时会这样做。)
你可以做到,只要它是成员函数中的最后一个元素,并且在返回后你会忘记那个对象曾经存在过......但是,就像那篇文章问的那样......你为什么要这样做?我不知道标准是怎么说的,但它确实给了我一种有趣的感觉:P
我想这有点像你是否曾经使用过 GOTO 语句,我个人有时会使用 GOTO 来清理 C 中的资源,尤其是在特殊情况下。
我想知道共享状态的含义是什么(我知道的模糊陈述):P
是的。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()
delete this
不能从非成员函数调用:)尽管与此线程没有直接关系,但我想澄清一下。我被问到一个问题,给定一个情况:
int* a = new int ;
int* b = a ;
delete a;
现在下一个语句安全吗?
cout<<*b ;
我的回答:删除 a 后, a指向的位置已被标记为删除,并且在任何时间点都可以将其分配给其他对象。因此,使用b访问值是不安全的,因为它可能在分配给其他对象后被修改。
注意:请不要反对,这只是一个澄清