首页 > 解决方案 > 存储数据的对象和存储指向数据的智能指针的对象

问题描述

假设我想在我的银河帝国中组织舰队。

class Fleet
{
    string m_commander;
    int m_totalShips;
}


class GalacticEmpire
{
    string m_coolName;
    string m_edgyTitleOfTheRuler;
    /*Problem line number1*/
}

GalacticEmpire是一个将拥有和控制仅属于我的帝国的一切的对象-它将存储其数据的所有字节。

但是 myGalacticEmpire不存在于 void 中(我的意思是技术上它确实存在),StarSystem它控制着 s。

class StarSystem
{
    string m_name;
    color m_starColor;
    /*Problem line number2*/
}

NowStarSystem不应该存储任何原始数据 - 它只需要能够指向Fleets 在其范围内的那个站点。

现在的问题。

应该如何GalacticEmpire存储Fleets 以便它可以访问它们并销毁它们(完全来自程序),同时StarSystem应该如何指向Fleetss 以便它可以迭代它们?换句话说,应该Problem line number1Problem line number2什么样子?

选项1:

问题行号 1 =vector<Fleet> m_fleets

问题行号2 =vector<shared_ptr<Fleet>> m_fleets

选项#2:

问题行号 1 = 问题行号 2 =vector<shared_ptr<Fleet>> m_fleets

标签: c++

解决方案


这似乎是对象设计中一个有趣的练习。让我们天真地尝试一下。

class GalacticEmpire
{
    std::string m_coolName;
    std::string m_edgyTitleOfTheRuler;
    std::vector<Fleet> fleets;
};

这似乎是正确的——Empire 拥有自己的舰队,它们被安排在容器(向量)中,我们不需要在这里使用任何间接方式——向量存储Fleet对象。

现在,让我们使用视图指针StarSystem

class StarSystem
{
    string m_name;
    color m_starColor;
    std::vector<Fleet*> fleets;
}

我们将填充StarSystem::fleets来自 的地址GalacticEmpire::fleet,乍一看似乎有效。

不幸的是,这个解决方案非常脆弱。如果Empire碰巧添加了新的舰队,它会通过将对象添加到GalacticEmpire::fleets向量来做到这一点,并使存储在StarSystem::fleets. 不是很好!

第二次尝试:

 class GalacticEmpire
 {
    // ...
    std::vector<std::unique_ptr<Fleet>> fleets;
 };

并存储由s ofStarSystem::fleets管理的(非拥有的)指针。这解决了我们添加新队列的问题——即使将新元素推送到向量 ivalidate 指向s 的指针,由所述 ptrs 管理的指针仍然有效。unique_ptrGalacticEmpire::fleetsunique_ptr

但是,此解决方案有两个缺点:您会失去性能。现在可以动态创建可以直接存储在车队向量中的对象。访问这些需要间接访问,这一切都会对性能造成严重影响。

另一个问题是合乎逻辑的——我们已经解决了添加新车队的问题,但是如果车队被移除了怎么办?我们确实需要从预期的 StarSystem 中清理这支舰队!

让我们想一想。很明显,一个StarSystem可以承载多个舰队,但一个舰队只能驻扎在一个单一的内部StarSystem。让我们使用这些信息:

class Fleet
{
    string m_commander;
    int m_totalShips;
    StarSystem* stationed_system;
};

我们将指向 StarSystem 的指针添加到该舰队本身托管。现在,当一个帝国失去它的一支舰队时,我们应该能够从驻扎在星际系统的舰队列表中清除该舰队。但是,我们如何找到它?在向量中迭代?这个比较慢。让我们改用 unordered_set,这样我们就可以在恒定时间内找到(并删除)一个舰队!

class StarSystem
{
    std::unordered_set<Fleet*> fleets;
};

现在,唯一剩下的就是确保我们在类之间引入某种类型的友谊,并添加一些私有和公共功能,以保证无论何时移除一个舰队,它也会从它的 StarSystem 中移除。这是留给读者的。


推荐阅读