我不太確定我需要一個對象池,但它似乎是最可行的解決方案,但有一些不想要的缺點與它相關聯。我正在製作一個遊戲,實體存儲在對象池中。這些實體不是直接分配給新的,而是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
隊列,這將讓這個標識將被重新-used,最後它的ID將被設置爲0.現在唯一的缺陷是,如果我銷燬一個實體然後立即創建一個新實體,之前銷燬的實體將被更新爲與剛創建。
即
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實體消滅他們。如果我能夠從池中獲取實體,或者存儲指向實際實體的指針副本,該怎麼辦?如何在銷燬時將所有其他重複實體置空?
即
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
所以你的問題是'object1'和'object2'指向相同的實際實體?但是,這不就是擁有一個游泳池嗎?如果你想避免使用'object1',那麼你必須'NULL'它。 – Manuzor
@Manuzor我感覺有點遲鈍,但是無論如何無視指針對我來說似乎有點黑客。 –
順便說一下,你可能想看看[placement new](http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new),它允許你調用構造函數和'Entity'類的析構函數,而不必使用'new'或在堆棧上分配對象。這樣'Entity'類不需要特別處理創建和清理之後。 – Manuzor