-1

我应该担心向量中有太多级别的向量吗?例如,我有 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

第二种方法要好得多,但我猜要慢得多。

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

谢谢

4

3 回答 3

2

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

几乎没有理由在类上使用向量来处理如此复杂的事情。具有正确定义接口的类不会使您的代码更有效率,但它将使将来的维护变得更加容易。

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

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

现在,如果pos.a, pos.b, pos.c,引用的向量索引pos.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类中使用向量,但由于它在方法中,您可以在以后删除向量滥用,而无需在其他地方更改任何代码(请参阅:得墨忒耳法则)!

于 2013-07-07T21:23:28.643 回答
1

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

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

(注意与号)。当您使用 b 时,您将使用原始向量。

但正如@delnan 指出的那样,您应该更担心您的代码结构——我相信您可以以更合适和可维护的方式重写它。

于 2013-07-07T21:01:12.863 回答
-1

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

鉴于我们所知甚少,您提供的代码还不错。

您展示的第一种和第二种方法在功能上是相同的。默认情况下,两者都将返回一个对象引用,但根据分配可能会导致复制。第二个肯定会。

Sasha 是对的,因为您可能需要引用而不是对象的副本。根据您使用它的方式,您可能希望将其设为 const。

由于您正在使用向量,因此每次调用都是固定时间并且应该非常快。如果您真的很担心,请确定通话时间并考虑每秒拨打电话的频率。

您还应该考虑数据集的大小,并考虑另一种数据结构(可能是数据库)是否更合适。

于 2013-07-07T21:13:04.733 回答