获取唯一编号并知道它们何时被释放

Posted

技术标签:

【中文标题】获取唯一编号并知道它们何时被释放【英文标题】:Getting Unique Numbers and Knowing When They're Freed 【发布时间】:2011-08-31 03:31:37 【问题描述】:

我有一个物理模拟(使用 Box2D),其中具有相同整数 ID 的物体不会发生碰撞,例如,属于同一角色的物体。我有一个问题,因为我需要能够为每个可能的实体获取一个唯一的数字,这样没有两个字符会意外地获得相同的 ID。实体的数量是有限的,但它们是根据模拟的要求创建和销毁的,因此一旦它们所属的实体消失,就有必要释放唯一 ID。

一个类World负责创建和销毁所有物体,也是管理唯一编号生成的实体,以及涉及物理模拟的任何其他事物。

到目前为止,我想到了两种方法,但我不确定哪种方法会更好,如果有的话:

保留vector<short>,数据是浮动的引用数,向量中的位置是ID本身。这种方法的缺点是在对操纵组 ID 的实体进行编码时会产生不必要的复杂性,因为它们需要确保告诉World 他们取出了多少引用。

保留vector<bool>,数据是该 ID 是否空闲,向量中的位置是 ID 本身。如果不存在空闲槽,则向量会随着对唯一 ID 的每次新调用而增长。缺点是一旦向量达到一定大小,就需要对整个模拟进行审计,但优点是实体能够获取唯一数字,而无需帮助管理引用计数。

李>

大家怎么看,有没有更好的办法?

【问题讨论】:

每个身体有一个对象吗?在这种情况下,您可以只比较对象的地址。 每个主体都有一个或多个附加的“形状”图元,它们有自己的过滤器 ID,因此一个主体可能有多个。我喜欢使用地址的想法,但过滤器数据存储为负数 short,(正数 ID 实际上意味着完全不同的东西,即无论如何总是与具有相似 ID 的形状发生冲突) 【参考方案1】:

您可以在您的主 World 对象中维护一个未使用 ID 的“空闲”列表作为单链表。

当一个对象被World 销毁(使其 ID 未被使用)时,您可以将该 ID 推送到空闲列表的头部。

当您创建一个新对象时,您可以执行以下操作:

If the free list is non-empty: pop the head item and take that ID.
Else increment a global ID counter and assign it's current value.

虽然您仍然可能用完 ID(如果您同时拥有超过计数器最大值的对象),但此策略将允许您回收 ID,并以 O(1) 运行时复杂性执行所有操作。

编辑:根据下面@Matthieu 的 cmets,std::deque 容器也可用于维护“免费”列表。此容器还支持具有O(1) 复杂性的push_front, pop_front 操作。

希望这会有所帮助。

【讨论】:

...太棒了。我很惭愧直到现在才考虑使用链表。 难道你还需要某种引用计数机制吗?您如何知道 ID 何时被使用? @Miguel Grinberg 我假设当World 销毁对象时,它也会将 ID 添加回列表(还假设 World 正在维护列表开始) @Miguel, ssell:没错。当一个对象(被世界)销毁时,它的 ID 被推送到空闲列表中以被回收。 @Clairvoire,Darren:不想成为派对大便,但是......您正在使用链表作为堆栈。使用deque 可以更好地实现堆栈,以获得更好的内存需求,这反过来可能会带来更好的缓存行为。【参考方案2】:

有几具尸体?如果您不重新分配整数,您是否会用完整数?最简单的解决方案是只使用一个整数来存储下一个 ID —— 当您将新 ID 分配给正文时,您将递增该整数。

【讨论】:

我同意这将是最好的,只要@Clairvoire 不希望使用超过unsigned 的最大值。即使那样,使用long long 也可以。 @ssell: floatdouble 使情况变得更糟。坚持整数。如果需要超过 2^32,请使用 long long 或任何适合您环境的 64 位整数数据类型。 @wallyk 是的,我正要编辑我的评论以改用long long。但很高兴你提到它! 如果您每秒用完一个 ID 30 次,则溢出一个 31 位整数需要 2 年以上。 ID 本身存储为short。我对此的主要担心是,随着模拟的进行,它可能会导致我们递增的整数溢出回 0,如果仍然存在具有低 ID 的非常旧的对象,它可能会找到另一个最近创建的对象相同的 ID,因此无法与之冲突

以上是关于获取唯一编号并知道它们何时被释放的主要内容,如果未能解决你的问题,请参考以下文章

何时释放 AudioRecord 对象?

何时释放带有“自动释放”的对象?

使用多个活动时何时正确释放相机?

分配和释放 VS。自动释放。为啥和何时?

Unity3D:如何检测按钮何时被按住和释放[重复]

何时使用自动释放变量? [复制]