Reputation: 353
I got this simple creature and AI classes. The Goal is to plug an AI to a creature and give to said AI the creature's reference.
Creature
class Creature
{
public:
explicit Creature(std::string&& name) : m_name(name) {}
void setAI(std::shared_ptr<AI>&& behavior)
{ m_behavior = std::move(behavior); }
void greet() { m_behavior->action(); }
const std::string& getName() const { return m_name; }
private:
std::shared_ptr<AI> m_behavior;
std::string m_name;
};
AI
class AI
{
public:
explicit AI(Creature& creature) : m_creature(creature) {}
void action() { std::cout << m_creature.getName() << std::endl; }
private:
Creature& m_creature;
};
Now depending in the order of action when I create the creature and set the AIs I get different result and fail to understand why.
Example 1: Not working. Only the last creature has a valid AI.
std::vector<Creature> atlas;
Creature& quokka = atlas.emplace_back(Creature("Quokka"));
quokka.setAI(std::make_shared<AI>(quokka));
Creature& wombat = atlas.emplace_back(Creature("Wombat"));
wombat.setAI(std::make_shared<AI>(wombat));
Creature& bilby = atlas.emplace_back(Creature("Bilby"));
bilby.setAI(std::make_shared<AI>(bilby));
for (Creature& creature : atlas) { creature.greet(); }
Example 2: This is working perfectly
atlas.emplace_back(Creature("Quokka"));
atlas.emplace_back(Creature("Wombat"));
atlas.emplace_back(Creature("Bilby"));
for (Creature& creature : atlas)
{
creature.setAI(std::make_shared<AI>(creature));
}
Where is the difference and why does example 1 fails to work ?
Upvotes: 0
Views: 27
Reputation: 12928
This is caused by the fact that when a std::vector
grows it will reallocate it's content. That means that all pointers and references to that vector will be invalidated.
You are storing a reference to a Creature
in you AI
class, and it get invalidated in you first example, since you add object to the vector after you have obtained the references.
In your second example, all the object are added first, then you take the references to them. Hence all the references are still valid.
Upvotes: 2