2013-07-02 140 views
0

我在设计实体组件系统的内存管理时遇到了一些问题,并且遇到了一些与设计细节有关的问题。这里就是我试图做(注意,所有这些类除外Entity实际上是虚拟的,所以会有很多不同的具体实现):内存管理设计

Program类将有Entity的容器。 Program将通过Entity循环并调用它们中的每一个更新。它也会有几个SubSystem,它也会在每个循环中更新。

每个Entity将包含两种类型的Component's。他们全部由内部的unique_ptr拥有,因为他们的生命周期与实体直接相关。一种类型UpdateableComponent将在调用Entity.update()方法时更新。第二种SubSystemComponent将从其各自的SubSystem内更新。

现在,这是我的两个问题。首先是一些Component将控制其父母Entity的生命周期。我目前的想法是Component将能够调用一个函数parent.die()这将改变Entity内的内部标志。然后,在Program完成循环更新后,它将循环第二次,并删除在上次更新期间标记为删除的每个Entity。我不知道这是否是一种有效或者聪明的方式,尽管它应该避免Entity死亡的问题,而其Component仍在更新。

第二个问题是我不知道如何从SubSystem内引用SubSystemComponent's。由于它们是从Entity内部引用unique_ptr,所以我不能使用shared_ptrweak_ptr,并且当拥有组件的Entity死亡时,标准指针会结束晃动。我可以在Entity内切换为shared_ptr,然后在SubSystem中使用weak_ptr,但我宁愿不这样做,因为整个问题是Entity完全拥有它的Component's。

所以两件事:

  • 可以将我的第一个想法可以以有意义的方式在改善?
  • 是否有实施weak_ptr排序的功能与unique_ptr一个简单的方法,或者我应该切换到shared_ptr,只是确保不创建多个shared_ptrSubSystemComponent
+0

我想你可能想对内存管理做更多的研究,除非你在这个设计上死心塌地;循环遍历整个分配的内存空间多次将不可扩展。智能指针始终是最初开始的一种很好且简单的方法。此外,已经有一些建立完善的C++库[垃圾收集](http://stackoverflow.com/questions/81062/garbage-collection-libraries-in-c)。 – Suedocode

+0

@Aggieboy我已经考虑过扩展问题,并且已经制定出只将部分数据加载到“实体”中,一次将我限制为几千个(可能最多10-20个)。如果我简单地调用一个bool getter,并且可以从容器中删除'Entity',那么第二个循环真的会效率低下吗?这种设计更重要的是提高代码的可重用性而不是性能,并且我可以在以后轻松优化瓶颈。 –

+0

在尝试更新组件之前,您可以简单地检查'hasToDie'标志,这不是问题。然而,'unique_ptr'明确地被设计为单一,严格的所有权。正如你已经指出的那样,只要多于一个的对象需要一个引用(它保证总是有效的或者至少可检查的),你就不会越过'shared_ptr'和可能的'weak_ptr'。 – arne

回答

1

灿我的第一个想法得到了有意义的改进?

很难说,不知道更多关于正在进行的工作的性质。例如,你没有说过关于你使用线程的任何信息,但是看起来你的设计通过循环遍历所有可能的更新来设置优先顺序。对于一些低延迟很重要的事情,或者有一些理想的优先选择,像这样的循环序列并不好,而其他时候它是理想的。

还有其他的方法来协调从程序组件驱动的去除实体:

  • 返回代码可能气泡到循环过的实体,触发来自实体的容器的擦除,
  • Observer模式或lambda/std::function可能允许程序指定清理行为。

是否有实现的weak_ptr排序与功能的unique_ptr一个简单的方法,

或者我应该只是切换到shared_ptr的,只是确保不创建多个子系统的shared_ptr组件

听起来像合理的合适。您甚至可以将shared_ptr包装在不可复制的类中以避免意外错误。

或者 - 如对上述实体的破坏 - 你可以使用事件,所以SubSystemComponent析构函数调用回到SubSystem协调SubSystemSubSystemComponent之间的联系。观察者模式是实现这一目标的一种方式,为lambda提供一个SubSystemComponent -side std::function更加灵活。无论哪种方式,Subsystem从其记录中删除SubSystemComponent