我应该担心向量中有太多级别的向量吗

Should I be worried about having too many levels of vectors in vectors?

本文关键字:向量 多级 担心 我应该 太多      更新时间:2023-10-16

我应该担心向量中的向量级别太多吗?例如,我有一个5级的层次结构,我有这样的代码我的整个项目:

rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d]

其中每个元素是向量。整件事是一个向量的向量。。。使用这个仍然应该比复制这样的对象快得多:

Block b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
// use b

第二种方法要好得多,但我想速度较慢。

如果我应该担心与此相关的性能问题,请给我任何建议,否则。。。

感谢

代码中的效率不会真正受到影响(向量随机访问的成本基本上是零),您应该关注的是向量数据结构的滥用。

对于像这样复杂的东西,你几乎没有理由在类上使用向量。具有正确定义接口的类不会提高代码的效率,但它会使将来的维护更加容易。

您当前的解决方案也可能遇到未定义的行为。以你发布的代码为例:

Block b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];

现在,如果pos.apos.bpos.cpos.d所指的向量索引不存在于其中一个向量中,会发生什么?您将进入未定义的行为,您的应用程序可能会出错(如果幸运的话)。

要解决此问题,在尝试检索Block对象之前,需要比较所有向量的大小。

例如

Block b;
if ((pos.a < rawSheets.size()) && 
    (pos.b < rawSheets[pos.a].countries.size()) &&
    (pos.c < rawSheets[pos.a].countries[pos.b].cities.size()) &&
    (pos.d < rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks.size()))
{
    b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];
}

你真的会在每次需要盖帽时都这么做吗?!!

可以这样做,或者你至少可以把它封装在一个类中。。。

示例:

class RawSheet
{
    Block & FindBlock(const Pos &pos);
    std::vector<Country> m_countries;
};
Block & RawSheet::FindBlock(const Pos &pos)
{
    if ((pos.b < m_countries.size()) &&
        (pos.c < m_countries[pos.b].cities.size()) &&
        (pos.d < m_countries[pos.b].cities[pos.c].blocks.size()))
    {
        return m_countries[pos.b].cities[pos.c].blocks[pos.d];
    }
    else
    {
        throw <some exception type here>;
    }
}

然后你可以这样使用它:

try
{
    Block &b = rawSheets[pos.a].FindBlock(pos);
    // Do stuff with b.
} 
catch (const <some exception type here>& ex)
{
    std::cout << "Unable to find block in sheet " << pos.a << std::endl;
}

至少,您可以继续在RawSheet类中使用向量,但由于它在方法中,您可以在以后删除向量滥用,而不必在其他地方更改任何代码(请参阅:Demeter定律)!

请改用引用。这不会复制对象,只是创建一个别名以使其更可用,因此性能不会受到影响。

 Block& b = rawSheets[pos.a].countries[pos.b].cities[pos.c].blocks[pos.d];

(注意电流)。使用b时,将使用原始向量。

但正如@delnan所指出的,你应该更加担心你的代码结构——我相信你可以用一种更合适、更可维护的方式重写它。

您应该担心具体的答案,因为我们不知道程序的约束是什么,甚至不知道它的作用是什么?

考虑到我们所知甚少,你给出的代码并没有那么糟糕。

您展示的第一种和第二种方法在功能上是相同的。默认情况下,两者都将返回对象引用,但根据指定情况,可能会生成副本。第二个肯定会。

Sasha是对的,你可能想要一个引用而不是对象的副本。根据您使用它的方式,您可能希望将其设为常量。

由于您使用的是向量,所以每次调用都是固定的时间,并且应该非常快。如果你真的很担心,给电话计时,并考虑一下每秒打电话的频率。

您还应该考虑数据集的大小,并考虑其他数据结构(也许是数据库)是否更合适。