【问题标题】:When is it appropriate to use "delete this"? [duplicate]什么时候适合使用“删除这个”? [复制]
【发布时间】:2009-06-24 22:34:28
【问题描述】:

可能重复:
Should objects delete themselves in C++?

在我的应用程序中,我创建了许多“拥有自己”的对象 - 在它们被创建并被告知“离开”之后,只有对象本身可以确定何时应该删除它。

例如,如果我正在编写游戏,我可能有多个 Enemy 对象。只有Enemy 对象知道它应该何时死亡。

因此,我最终在Enemy 对象内的一些成员函数中使用了delete this。这是不好的形式吗?这是我应该避免的事情吗?如果是,处理这种情况的正确方法是什么?

【问题讨论】:

标签: c++ memory-management


【解决方案1】:

需要注意的是,如果太多的成员函数有自删除的副作用,很容易在删除后不小心使用了对对象的引用。

避免这种情况的一种方法是延迟删除 - 即,将对象放在一个列表中,然后在游戏的主循环中,在一个滴答的开始/结束时删除该列表中的所有内容。

【讨论】:

  • 哦,听起来像垃圾收集! :-)
  • @Tanktalus:对我来说听起来不像垃圾收集,因为当满足某些逻辑时,对象负责删除自己。
  • @Paul:最初的问题听起来不像 GC。这个答案可以。除了搜索地址以找出不再引用的内容之外,您将自己添加到要在下一个可用周期收集的垃圾列表中。
  • 所以不要叫它删除自己,叫它确定它是否“被杀死”。你是对的,在所有引用对象都决定不再对它感兴趣之前,你不应该删除该对象。 GC 对 OO 编程至关重要,它只是如何实现以及由谁实现的问题。
  • GC的基本属性是系统根据结构信息(即对象引用图)自动判断是否删除对象。当您需要明确告诉它删除某些内容时,即使该删除稍后发生,也不是 GC。
【解决方案2】:

取决于内存管理策略。在某些情况下,它确实是有道理的,而且是正确的。例如,在像 COM 这样的引用计数系统中,当引用计数降至零时,对象会执行 delete this。

【讨论】:

    【解决方案3】:
    For example, if I was writing a game, I might have multiple Enemy
    

    对象。只有 Enemy 对象知道 什么时候该死。

    敌方物体可能知道它何时进入“死亡”状态,是的。但这不一定等同于“对象应该被删除”。

    想想所有其他可能引用它的对象吗?他们可能随时尝试调用 Enemy 对象上的函数(例如 TakeDamage()),如果在没有通知他们的情况下删除了该对象,您可能会遇到崩溃。他们怎么知道他们射击的敌人已经死了?

    所以 Enemy 对象知道它何时死亡,但不知道何时应该将其删除。它不拥有自己。

    那么谁拥有它?

    游戏世界可能是一个不错的选择。当敌人死亡时,它会向游戏世界发送一条消息说它已经死亡,然后游戏世界可以负责确保没有人持有指向它的指针,最后在安全的情况下删除对象。

    【讨论】:

      【解决方案4】:

      这对我来说似乎很奇怪,我自己更喜欢有人或某事摆脱他们。对某人引用该对象的恐惧对我来说只是可怕的。 “子”方法似乎也很有可能在不知不觉中破坏对象。当您返回更高级别的方法时:您正在对一个不存在的对象进行操作。

      听起来你正在发明引用计数,也许明确地使用引用计数模式。

      或者让对象将自己添加到“被销毁”列表中 - 你自己就有了一个垃圾收集系统。

      【讨论】:

        【解决方案5】:

        只要敌人管理对他们的所有引用(例如,单位列表、组中单位列表等)就可以(并且经常使用)。

        但如果你想更安全一点,敌人应该注册自己以在程序执行中的某个“安全点”运行一些破坏例程(例如,参见 Qt 中的QObject::deleteLater()。

        【讨论】:

          【解决方案6】:

          您可以对对象使用 shared_ptrs 以在不再有对它们的引用时自动清理它们。

          或者调用类的析构函数。

          【讨论】:

          • 太糟糕了,点击错误...再次取消投票。
          【解决方案7】:

          说实话,您应该尽量避免这样做。否则你可能会删除一些被其他东西使用的东西,并以一个非常奇怪的结果和可能的内存泄漏来结束。

          我认为对象应该在析构函数中删除它的资源。你的班级应该使用另一个班级来知道敌人何时死亡。

          【讨论】:

            【解决方案8】:

            引用对象应该执行删除,并且应该通过询问对象是否满足删除条件来执行此操作。条件之一(除了在游戏中被淘汰)是有多少其他对象仍然引用该对象。这可以通过静态引用计数来跟踪。通常,如果您仔细编写它,您可能能够以这样一种方式构建它,即只在游戏循环中的一个位置跟踪敌人。该位置将检查冲突和其他条件,当它准备好删除对象时,它不必询问是否可以删除,因为它知道它是唯一的客户端,并且可以安全地取消引用它分配的内容。

            【讨论】:

              【解决方案9】:

              抽象地说,我认为您不希望对象自行删除。

              您要做的是创建一个控制结构,从对象中检索到“死亡”的信号或消息,在这种情况下,控制结构将“删除”或对对象采取特定的必要操作对象。

              这样,您可以将对象的控制权留在控制结构上是否存在,并且当一切都具有集中控制单元时,您可以防止对已删除对象的潜在调用。

              另外,请记住区分您所说的士兵“垂死”和实际从记忆中“删除”的对象。死亡部分,对象本身可以通过设置一个标志来完成,例如“dead = true”。但是从内存中删除对象应该通过我指的控制结构来完成。

              【讨论】:

                猜你喜欢
                • 2014-05-07
                • 2011-09-13
                • 2010-10-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2019-02-28
                • 2019-09-17
                • 2019-08-25
                相关资源
                最近更新 更多