我不太确定我是否需要一个对象池,但它似乎是最可行的解决方案,但有一些与之相关的不需要的缺点。我正在制作一个游戏,其中实体存储在对象池中。这些实体不是直接用 new 分配的,而是std::deque
为它们处理内存。
这是我的对象池或多或少的样子:
struct Pool
{
Pool()
: _pool(DEFAULT_SIZE)
{}
Entity* create()
{
if(!_destroyedEntitiesIndicies.empty())
{
_nextIndex = _destroyedEntitiesIndicies.front();
_destroyedEntitiesIndicies.pop();
}
Entity* entity = &_pool[_nextIndex];
entity->id = _nextIndex;
return entity;
}
void destroy(Entity* x)
{
_destroyedEntitiesIndicies.emplace(x->id);
x->id = 0;
}
private:
std::deque<Entity> _pool;
std::queue<int> _destroyedEntitiesIndicies;
int _nextIndex = 0;
};
如果我销毁一个实体,它的 ID 将被添加到_destroyedEntitiesIndicies
队列中,这将使 ID 被重新使用,最后它的 ID 将设置为 0。现在唯一的陷阱是,如果我销毁一个实体,然后立即创建一个新实体,之前销毁的实体将更新为刚刚创建的同一实体。
IE
Entity* object1 = pool.create(); // create an object
pool.destroy(object1); // destroy it
Entity* object2 = pool.create(); // create another object
// now object1 will be the same as object2
std::cout << (object1 == object2) << '\n'; // this will print out 1
这对我来说似乎不正确。我该如何避免这种情况?显然上述情况可能不会发生(因为我会将对象销毁延迟到下一帧)。但这可能会在将实体状态保存到文件或类似的东西时引起一些干扰。
编辑:
假设我做了 NULL 实体来销毁它们。如果我能够从池中获取实体,或者存储指向实际实体的指针副本怎么办?销毁时如何使所有其他重复实体为空?
IE
Pool pool;
Entity* entity = pool.create();
Entity* theSameEntity = pool.get(entity->getId());
pool.destroy(entity);
// now entity == nullptr, but theSameEntity still points to the original entity