Reputation: 109
I have a quick question.
I started learning C++ a while ago and have always used vectors with shared pointers of objects in them. Or at least smart pointers.
I'm currently programming a game and I was thinking about why I would use smart pointers.
Assume I have a Game class and it has a vector of players.
When would I want to choose for
vector<Player> players
and when would i want to choose for vector<shared_ptr<Player>>
?
Upvotes: 2
Views: 1242
Reputation: 1856
Use shared_ptr
s if the state of the entities is accessed other than in the vector. Also if you make an event-loop, with events like "player collided with other entity". You need to copy a pointer/reference, else you cannot change the state of the entities.
Another important thing is when the entity dies but an event with the entity is not handled, so the entity is deleted from the vector. When you use shared_ptr
, the entity lives further, until the event in the eventqueue is deleted. When you store the whole player in the vector, the pointer stored in the event-object is not pointing to the correct entity anymore, if the vector changes its size. When you use a shared_ptr
, the entity can be used normally, even if it is not existing in the vector anymore. But it is better to use std::weak_ptr
in the event, that the entity is deleted, when it is dead, weak_ptr
can check if the pointer is a dangling pointer which means the entity is dead and no event needs to be handled.
Using levels/dimensions, in which the vector of entities lives: When some entity goes to another level, the entity needs to be moved to that level, copying the whole struct is not the best idea. So the best idea is to use some pointer type like shared_ptr, but I recommend to std::move
the shared_ptr
to reduce reference counting overhead. With std::move
the shared_ptr is as fast as a raw ptr.
Virtual classes of entities: When you are writing a game in a 2D or 3D world, you want to store many entities of different kind in the vector, you must use some pointertype to refer to the object, because the entities may have different size.
Fixed player count: If you are programming a game with fixed count of players like a card-game, you do not move the players nor you delete one (however you can just set a flag to indicate that the player is dead and you do not need to erase the entity from the vector), the best way is to use std::vector<Player>
.
I think, using shared_ptr
living in the vector and with weak_ptr
s referencing in events is the best way to manage entities. While weak_ptr
(the faster way) does not keep the memory of the Entity alive, the pointer needs to be checked every time.
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>;
};
Upvotes: 2