Search code examples
c++goto

C++: speeding up a for-loop using goto?


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?


Solution

  • 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.