C ++:使用goto加速for循环?

时间:2014-01-27 14:29:57

标签: c++ goto

在以下for循环中,如果conditionAconditionBconditionC都评估为true,我就不会做任何事情。

for (int i = 0; i < imax; ++i) {
    bool conditionA;
    // evaluate conditionA

    bool conditionB;
    // evaluate conditionB

    bool conditionC;
    // evaluate conditionC

    if (conditionA && conditionB && conditionC) continue;

    // do something
}

如果conditonA评估为false,则无需评估conditionBconditionC。所以我似乎可以通过以下方式编写来加速循环。

for (int i = 0; i < imax; ++i) {
    bool conditionA;
    // evaluate conditionA

    if (conditionA) {
        bool conditionB;
        // evaluate conditionB

        if (conditionB) {
            bool conditionC;
            // evaluate conditionC

            if (conditionC) continue;
        }
    }   

    // do something
}

现在看起来很丑陋,乍看之下并不明白。似乎使用臭名昭着的goto代码变得更加优雅:

for (int i = 0; i < imax; ++i) {
    bool conditionA;
    // evaluate conditionA
    if (!conditionA) goto doSomething;

    bool conditionB;
    // evaluate conditionB
    if (!conditionB) goto doSomething;

    bool conditionC;
    // evaluate conditionC
    if (conditionC) continue;

    doSomething:

    // do something
}

这是否可以作为加速循环的方法,或者编译器是否足够聪明,以至于代码的第一个版本实际上与第二个和第三个版本一样快?如果它不是,是否有比使用goto更好的选择?

4 个答案:

答案 0 :(得分:21)

我会将条件的评估转移到单独的函数中,然后执行:

for (int i = 0; i < imax; ++i) {
    if (conditionA() && conditionB() && conditionC()) continue;

    // do something
}

如果conditionA返回false,则永远不会调用conditionB,依此类推。

这也将使您的功能更简洁,更简洁,将职责分配到其他功能中。

如果你没有充分理由像这样“提前退出”,你可以完全避免使用continue

for (int i = 0; i < imax; ++i) {
    if (!(conditionA() && conditionB() && conditionC())) {
      // do something
    }
}

或者使用De Morgan定律获取!conditionA() || !conditionB() || !conditionC - 无论您喜欢哪种。

答案 1 :(得分:4)

在尝试加快速度之前,如果循环确实是瓶颈,请咨询您的探查器。如果不是这样,请保持代码的可读性和可维护性(与可能稍微快一点,可能更慢,但肯定是错误和无法读取的混乱)相反,并将其留给编译器的能力加快速度。

如果循环是瓶颈,请尝试任何想法, profile ,并比较结果。没有人可以肯定地说出你的编译器可以优化的东西。

在微观性能优化方面,永远不要相信除了你的探查器以外的任何人。 编译器在优化和优化方面有所不同,人类在预测这些优化的节省方面特别糟糕。

但是,如果条件不是太复杂,我敢打赌编译器会优化掉布尔变量,并留下类似的东西

for (int i = 0; i < imax; ++i) {
  if(evalConditionA() && evalConditionB() && evalConditionC())
    continue;
  doSomething:
}

你总能做的是对任何条件变为错误的概率进行评估,并将最先考虑的条件设置为最有可能触发短路评估,因此其他条件不需要经常评估。

答案 2 :(得分:0)

好吧,和往常一样,如果你对表演感到疑惑,那就做一个基准。否则,我认为最好的解决方案实际上取决于您的背景。例如,如果您可以在估价中作为条件或作为单独的函数(或最坏情况下的宏),您的第一个解决方案是最好的:

for (int i = 0; i < imax; ++i) {
    if (! (evaluate conditionA) && (evaluate conditionB) && (evaluate conditionC)) {
        // do something
    }
}

然后懒惰的评估会有所帮助,根据你的工作,你的编译器可能能够通过一些优化选项来优化你的评估。

我还建议您不要使用if (condition) continue;,而是if (!condition) { /* do something */ },这有助于更好地理解算法。不要忘记有一天某人会读你的代码,而有人可能是你!

答案 3 :(得分:0)

C ++编译器(至少是Visual Studio)已经完成了你想要的工作。

if( bCondA && bCondB && bCondC )

如果bCondA == false,则其他人未经过验证。 对所有编译器都应该如此。