我有一个简单的问题。
我不久前开始学习C ++,并且总是使用带有共享对象指针的向量。或者至少是智能指针。
我正在编写一个游戏,我在考虑为什么要使用智能指针。
假设我有一个Game类,它有一个玩家矢量。
我希望何时选择
vector<Player> players
以及何时选择vector<shared_ptr<Player>>
?
答案 0 :(得分:0)
如果访问实体的状态而不是向量,请使用shared_ptr
s。此外,如果您使用“玩家与其他实体相撞”等事件进行事件循环。您需要复制指针/引用,否则您无法更改实体的状态。
另一个重要的事情是,当实体死亡但未处理实体的事件时,将从矢量中删除该实体。当您使用shared_ptr
时,实体会继续存在,直到事件队列中的事件被删除。当您将整个播放器存储在向量中时,如果向量更改其大小,则存储在event-object中的指针不再指向正确的实体。当您使用shared_ptr
时,即使实体不再存在,也可以正常使用该实体。但最好在事件中使用std::weak_ptr
,删除实体,当它死了,weak_ptr
可以检查指针是否是悬空指针,这意味着实体已经死亡,没有事件需要待处理。
使用级别/维度,其中实体的向量存在:当某个实体进入另一个级别时,实体需要移动到该级别,复制整个结构不是最好的主意。所以最好的想法是使用像shared_ptr这样的指针类型,但我建议std::move
使用shared_ptr
来减少引用计数开销。使用std::move
,shared_ptr与原始ptr一样快。
虚拟实体类:当您在2D或3D世界中编写游戏时,您希望在向量中存储许多不同类型的实体,您必须使用某些pointertype来引用该对象,因为实体可能具有不同的大小。
修正了玩家数量:如果您正在使用固定数量的玩家(如纸牌游戏)编写游戏,则不会移动玩家,也不会删除玩家(但是您可以设置一个表示玩家已死的标志,你不需要从向量中删除实体),最好的方法是使用std::vector<Player>
。
我认为,使用shared_ptr
生活在向量中并使用weak_ptr
引用事件是管理实体的最佳方式。虽然weak_ptr
(更快的方式)不会使实体的内存保持活动状态,但每次都需要检查指针。
if(fixed count of players
&& there are no other entities
&& there are no virtual subclasses of Player) {
class Player { ... };
using player_collection = std::vector<Player>;
using reference_to_player = Player*;
} else {
class Entity { public: ... virtual ~Entity(); };
class Player: public Entity { ... };
using entity_collection = std::vector<std::shared_ptr<Entity>>;
using reference_to_entity = std::weak_ptr<Entity>;
};