我是否应该担心载体中含有太多水平的载体?

时间:2013-07-07 20:58:41

标签: c++

我是否应该担心载体中含有太多水平的载体? 例如,我有一个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

第二种方法更好,但我想更慢。

如果我担心与此相关的性能问题,请给我任何建议, 或者......

由于

3 个答案:

答案 0 :(得分:2)

效率不会真正影响你的代码(矢量随机访问的成本基本上没什么),你应该关注的是滥用矢量数据结构。

你应该在类上使用向量来处理像这样复杂的事情。具有正确定义的接口的类不会使您的代码更有效,但它将来会使维护变得更加容易。

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

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

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

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

e.g。

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类中使用向量,但是如果它位于方法内,您可以在以后删除向量滥用,而无需在其他位置更改任何代码(见:Law Of Demeter)!

答案 1 :(得分:1)

改为使用引用。这不会复制对象,只是创建别名以使其更有用,因此不会触及性能。

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

(观看&符号)。使用b时,您将使用原始矢量。

但正如@delnan所说,你应该更担心你的代码结构 - 我相信你可以用更合适和更可维护的方式重写它。

答案 2 :(得分:-1)

您应该担心具体的答案,因为我们不知道您的计划的约束条件甚至是什么?

鉴于我们所知道的很少,你提供的代码并不是那么糟糕。

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

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

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

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