2012-07-10 17 views
3

我將如何存儲大量的對象(如子彈或不斷變化的),然後通過它們的索引刪除它們? 我聽說vector :: erase不是很有效率。在C++中存儲大量短命的遊戲對象

+1

使用std :: lists?或者甚至是std :: unordered_map和std :: list的組合,其中映射的關鍵是觸發項目符號或擁有列表中的對象的實體。 – 2012-07-10 15:50:56

+0

你想把每個項目符號存儲爲一個單獨的對象嗎?你爲什麼不把它們作爲一個數量類型存儲?你有多少種不同類型的彈藥? – KRyan 2012-07-10 15:51:34

+2

重新使用對象。把「死」的放在數組的尾部(一個簡單的交換),並跟蹤最後的「實時」項目符號索引。 – Cameron 2012-07-10 15:51:36

回答

2

使用std::map(或C++ 11s std::unordered_map),這些容器對於插入和擦除操作具有更好的分期運行時複雜性。 std::list也是一個選項(它是顯而易見的選擇,但我首先提到了其他選項,因爲它們還允許在許多遊戲場景中進行快速查找/搜索,這更加重要)。

在更高層次上,您應該閱讀C++容器以及一般運行時複雜性。良好的性能對集裝箱結構的明智選擇至關重要。

+0

'unordered_map'可能更適合如果你經常插入和刪除很多對象。 O(日誌N)插入和刪除時間將會增加。 – Rook 2012-07-10 15:53:04

1

unordered_set<Bullet*>會做的很好。那麼你可以簡單地在任何地方使用Bullet*並忘記索引。最好從一個對象池或類似的東西分配。

或者,由於標準好心搞砸了的界面,你可能需要代替std::unordered_map<Bullet*, std::unique_ptr<Bullet>>爲更好的異常安全等。

0

從我極其有限的遊戲引擎編程二手知識中,儘可能避免動態內存分配。因此,unordered_setlist將成爲頻繁清除「大量」的主要因素。

編輯:閱讀@詹姆斯甘孜的回答後,我意識到,@交換取出子彈與最後一​​個元素不起作用,因爲它改變了實彈指數的卡梅倫的建議。我想你不得不使用詹姆斯的建議,或者可能有點向量來標記死亡子彈。

保持項目符號壓縮在一個數組中對於緩存的性能也是很好的。哈希表會緩存好於std::map的紅黑樹,但是如果您已經通過索引引用了項目符號,爲什麼會產生散列開銷?

0

如果你確定由它們在向量索引子彈,然後erase是不是一個好主意;它會改變以下所有元素的索引。子彈由其索引標識的事實在一定程度上限制了您的選擇。在這種情況下,最好的解決方案可能是簡單地將條目標記爲無效,並在稍後重新使用它,或者通過保留無效索引列表(很容易在std::vector中完成),或者只需在每次要創建新的子彈。如果你有不同類型的子彈(你可能會隨着遊戲的發展),你仍然需要動態分配子彈,並在向量中保留一個指針;空指針對無效是一個很好的選擇。

0

vector::erase,因爲它需要將所有包含下列元素,以填補空間,以維護秩序不是很有效。然而,這聽起來像你並不需要保存的順序,在這種情況下,你可以通過在最後用一個替換它,然後丟棄最後一個元素更快速地刪除元素:

std::swap(bullets[index_to_remove], bullets.back()); 
bullets.pop_back(); 
1

(中)着名Alexandrescu考慮短生活動態小對象慢新/免費運營商的主要問題,並建議使用自定義分配器。 std :: map會使用很多這樣的對象(它在內部使用紅黑樹),所以最好使用預分配對象池或std :: map自定義分配器(可能從Alexandresu的Loki庫中獲取一個) )