在以下for
循环中,如果conditionA
,conditionB
和conditionC
都评估为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
,则无需评估conditionB
和conditionC
。所以我似乎可以通过以下方式编写来加速循环。
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
更好的选择?
答案 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,则其他人未经过验证。 对所有编译器都应该如此。