C++;安全对象删除 我写了一个比较大的C++项目,并且有一个对象删除的问题。确切地说,这个项目是一个类似流氓的游戏
我有一个类C++;安全对象删除 我写了一个比较大的C++项目,并且有一个对象删除的问题。确切地说,这个项目是一个类似流氓的游戏,c++,smart-pointers,delete-operator,C++,Smart Pointers,Delete Operator,我有一个类Npc,它是游戏中的每一个怪物。它们被创建并存储在一个单独的类中,存储,该类负责它们的管理(加载、保存、创建、删除等)。每当怪物死亡时,相应的对象npc必须被删除并完全销毁。删除对象本身不是问题,我只是从存储中调用了一个方法。问题是代码中包含了很多指向这个已经死了的npc的指针,这些指针现在是无效的,尝试使用它们会导致很多问题。例如: 在他死之前,可能有一个他打算执行的动作 他站在一块磁砖上,记录着一个指向他的指针 他可能参与了一些持续的活动,比如抓人 代码中有很多这样的指针,因此几乎
Npc
,它是游戏中的每一个怪物。它们被创建并存储在一个单独的类中,存储
,该类负责它们的管理(加载、保存、创建、删除等)。每当怪物死亡时,相应的对象npc必须被删除并完全销毁。删除对象本身不是问题,我只是从存储中调用了一个方法。问题是代码中包含了很多指向这个已经死了的npc的指针,这些指针现在是无效的,尝试使用它们会导致很多问题。例如:
在他死之前,可能有一个他打算执行的动作
他站在一块磁砖上,记录着一个指向他的指针
他可能参与了一些持续的活动,比如抓人
代码中有很多这样的指针,因此几乎不可能简单地跟踪它们。我需要的是某种方法来确定一个npc
已经死了,并且该地址上没有存储任何实际对象,这样仍然有这个指针的代码部分就可以对他的死做出适当的反应
我自己提出了几个想法,但到目前为止,没有一个对我来说真的很好:
- 我可以询问
存储
类在这样的地址上是否有对象。潜在的问题是,删除对象后,可能会在同一地址上分配另一个对象,这将导致错误
- 我可以通知所有可能使用无效指针的位置。这是一个坏主意,因为这样的地点的数量会随着时间的推移而增加,这样做是一件痛苦的事情
- 我可以实现一些版本的智能指针,但我不确定使用哪个版本
tl;dr version:我需要一个解决方案,它可以告诉我指针是否指向一个对象,或者它是否指向在原始对象删除后分配的空闲内存块或其他对象。使用弱指针如何?如果您将Npc
存储在std::shared_ptr
(C++11,对于C++03使用std::tr1::shared_ptr
),则可以创建引用shared_ptr
的std::弱_ptr
(C++11,对于C++03使用std::tr1::弱_ptr
)。当shared\u ptr
实际删除其对象时,所有弱\u ptr
都将能够解决这个问题
尽管我想知道为什么要删除仍在其他地方使用的Npc
s(例如,仍有操作)。如果您不想让所有其他引用发现您删除了Npc
,而是希望Npc
在所有引用消失后消失,那么使用共享的ptr
本身(没有弱ptr
)将正常工作。根据您提供的信息,我能建议的是你实施这个计划。
如果有代码需要对NPC的死亡做出反应,那么这种模式就是最好的选择。在NPC死亡时,将通知具有指向您的NPC指针引用的代码部分,并使其指向NPC指针的副本为空,并在需要时对NPC的死亡作出反应。在NPC被实际删除之前,死亡通知会发送给所有观察员
有了这个模式,你可以实现“英雄每杀死一个怪物就获得50点生命”这样的机制,而且它很容易扩展
如果没有代码需要对NPC的死亡做出积极反应,并且只需要处理NPC死亡的情况,您也可以使用Kevin Ballard的建议,即使用共享ptr
。一个选项是在类中包含引用计数。当某个其他对象(例如房间)将持有指向npc的指针时,房间有责任增加npc的引用计数。现在,不只是删除一个已死亡的npc,而是将其标记为已死亡(如果您还没有正确的标记,则通过另一个新的数据成员),并且仅在其引用计数为零时删除。room对象还负责定期检查该标志,如果它知道npc已死亡,则会减少其引用计数(如果计数现在为零,则会导致事后删除)。每次释放/失效内存时,如何将其设置为nullptr
:PYou已经为你的问题添加了一个答案:使用智能指针。我建议使用std::shared_ptr@SingerOfTheFall,我想你想说的是,每当我做删除pnpc代码>我应该做pnpc=0代码>。但是,如果程序中的其他地方存储了另一个等于pnpc的指针,它将不会被设置为t0,因此我想这不起作用。我想使用我描述的方法,因为游戏机制就是这样工作的。NPC随时都可能死亡,他不能再采取行动或成为地图的一部分是完全有道理的。我不希望在NPC死后执行任何有意义的代码,确保这一点的一种方法是在他死后立即删除相应的对象。@Saage:我认为如果NPC死了,你会主动删除它的动画,并在删除NPC之前删除它在地图上的存在(或者可能作为其破坏的一部分,尽管这可能是个坏主意),而不是依赖地图和操作列表来实现Npc的消失。通过这种方式,您可以查询操作列表的大小,并确保这实际上是挂起操作的计数。我想我最终会使用shared\u ptr
,因为它听起来更简单,但观察者模式是一个好主意,我肯定发现它有用,谢谢!