这不是我第一次获得RuntimeError: underlying C/C++ object has been deleted。我已经解决了很多次,以一种随机但直观的方式更改我的代码,但是现在我又面对了这一点,只是不知道为什么会发生...
我需要的是一种通用的方法来应对和解决此错误。

我不会在这里发布代码示例,因为我的项目太复杂了,我只是无法弄清错误所在。还有,因为我不仅在这种情况下要求通用解决方案。

为什么可以删除“基础C / C++”对象?
如何避免呢?
如何测试基础对象是否存在?

最佳答案

您无法测试基础对象是否存在(例如,是否已被“删除”)。您可以采用一些“诡计”来“帮助”解决此问题,但是我不建议这样做。相反,恕我直言,我猜您的设计缺乏强大的所有权语义。 (根据问题的复杂程度和您的 Realm ,这可能是必需的,但如果可以避免的话,我建议您反对。)

您的问题是所有权语义。与使用内存“垃圾收集”的其他语言相反,最特别是在C++中,必须在设计时对“谁拥有什么”有深刻的了解。您的设计应使其“容易且显而易见”知道存在哪些对象以及谁“拥有”它们。

通常,这意味着将对象的“创建”和“删除”集中到某种类型的“父”对象中,而对于“这是谁的对象”从来没有任何疑问。和“您管理的对象是什么?”

例如,“父”类将分配“需要”的成员对象,只有该父对象才能删除这些对象。父级的析构函数可确保删除这些成员,因此这些对象不会意外“遗留”。因此,父级“知道”其成员对象,并且当父级消失时,您知道成员对象也消失了。如果您的设计是紧密耦合的,则成员对象可以引用父对象,但这是所有权语义的“池的深端”(通常不建议这样做)。

某些设计可能会非常复杂。但是,通常,所有权语义绝不应该复杂:您应该始终知道“谁拥有什么”,因此,您应该始终知道“什么对象存在”。

垃圾收集语言还可以进行其他设计,其中对象可能是“自由代理”,并且您相信垃圾收集器会进行“艰苦的工作”以清理您丢失的对象。 (我不只喜欢那些设计,而是承认它们有时会基于独特的问题域在其他语言中被接受。)

如果您的C++设计依赖于此类“自由代理”对象,则可以编写自己的垃圾收集器或自己的“实用程序所有者”来清理它们。例如,MyFreeAgent构造函数可以向MyGarbageCollector注册自己,而MyFreeAgent析构函数会将其自身从MyGarbageCollector注销。因此,MyFreeAgent可以“清理” MyGarbageCollector实例,或者甚至可以使用“MyFreeAgent”杀死delete this;自己,并且您会知道它已经消失了(因为它的析构函数会从MyGarbageCollector中注销自身)。在这种设计中,单个MyGarbagageCollector总是“知道”存在哪些MyFreeAgent实例。

这样的设计是“池的最深处”,即使它们起作用,也应格外谨慎,因为它们具有大规模分解系统的强大潜力。 (我使用过它们,但是您必须确保这个问题确实可以得到这样的设计。)

09-09 20:03