存储数据的对象和存储指向数据的智能指针的对象

Objects storing data and objects storing smart pointers to data

本文关键字:存储 数据 对象 指针 智能      更新时间:2023-10-16

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

class Fleet
{
string m_commander;
int m_totalShips;
}

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

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

但是我的GalacticEmpire并不存在于虚空中(我的意思是技术上它确实存在(,它控制着StarSystem

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

现在StarSystem不应该存储任何原始数据 - 它只需要能够指向其边界内的Fleet站。

现在的问题来了。

GalacticEmpire应该如何存储Fleet以便它可以访问它们并销毁它们(完全来自程序(,以及同时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

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

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

这似乎是对的 - 帝国拥有自己的舰队,它们排列在容器(矢量(中,我们不需要在这里使用任何间接 - 矢量存储Fleet对象。

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

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

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

不幸的是,这种解决方案非常脆弱。如果Empire碰巧在其部队中添加了新的舰队,它将通过向矢量添加对象来做到这一点GalacticEmpire::fleets并将存储在StarSystem::fleets中的地址无效。不好!

第二次尝试:

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

并且StarSystem::fleets存储(非拥有(指针由unique_ptrGalacticEmpire::fleets管理。这为我们解决了添加新队列的问题 - 即使将新元素推送到矢量也会使指向unique_ptrs 的指针有效,由所述 ptrs 管理的指针仍然有效。

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

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

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

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

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

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

现在,唯一剩下的就是确保我们在职业之间引入某种类型的友谊,并添加一些私人和公共功能,这将保证每当舰队被移除时,它也会被从它的星际系统中移除。这是留给读者的。

我不确定我是否得到这个问题,但如果您事先知道有多少个舰队,您可以创建一个Fleet数组

class GalacticEmpire
{
Fleet* fleet = new Fleet [10]; //this is a pointer to the first position of a 10 size Fleet array
string m_coolName;
string m_edgyTitleOfTheRuler;
/*Problem line number1*/
}

如果我没记错的话,如果您使用的是 1 个文件,则需要在银河帝国之前声明舰队级。 此外,如果您不知道队列规模,则可以改用链表。

编辑:当您用完内存后,您必须释放内存delete[] fleet;