通过参考在矢量槽中放置和修改对象

Emplacing and modifying object in vector trough reference

我得到了这个简单的生物和 AI 类。目标是将一个 AI 插入一个生物,并向所述 AI 提供该生物的参考。

生物

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;
};

现在根据我创建生物和设置 AI 时的动作顺序,我得到不同的结果并且无法理解为什么。

示例 1: 无效。只有最后一个生物有有效的 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(); }

示例 2: 这非常有效

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));
}

区别在哪里?为什么示例 1 无法运行?

这是因为当 std::vector 增长时它会重新分配它的内容。这意味着指向该向量的所有指针和 引用 都将失效。

您正在 AI class 中存储对 Creature 的引用,并且在您的第一个示例中它变得无效,因为您在获得之后将对象添加到向量中参考资料。

在您的第二个示例中,首先添加所有对象,然后获取对它们的引用。因此,所有参考资料仍然有效。