In the following for
-loop, I don't do anything if conditionA
, conditionB
, and conditionC
all evaluate to 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
}
If conditonA
evaluates to false
, it becomes unnecessary to evaluate conditionB
and conditionC
. So it seems that I can speed up the loop by writing it in the following way.
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
}
Now this looks ugly and is not understood at first glance. It seems that using the infamous goto
the code becomes much more elegant:
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
}
Does this work as a method for speeding up the loop or is the compiler smart enough that the first version of the code is actually as fast as the second and third version? In case it isn't, is there a better alternative than using goto
?
I would move the evaluation of the conditions into separate functions and then do:
for (int i = 0; i < imax; ++i) {
if (conditionA() && conditionB() && conditionC()) continue;
// do something
}
If conditionA
returns false
, conditionB
will never be called, and so on.
This will also make your function shorter and more concise, dividing responsibilities up among other functions.
If you have no good reason for doing an "early exit" like that, you can avoid using continue
altogether:
for (int i = 0; i < imax; ++i) {
if (!(conditionA() && conditionB() && conditionC())) {
// do something
}
}
Or use De Morgan's law to get !conditionA() || !conditionB() || !conditionC
- whichever you prefer.