426

Is it possible to use the break function to exit several nested for loops?

If so, how would you go about doing this? Can you also control how many loops the break exits?

9
  • 11
    Instead of using break or goto to exit multiple nested loops, you can enclose that particular logic in a function and use return to exit from multiple nested loops. This will maintain the aesthetics of your code and will prevent you from using goto which is a bad programming practice. Commented Aug 26, 2019 at 13:49
  • 8
    why goto is bad programming practice? it's widely used in kernel.
    – None
    Commented Feb 23, 2022 at 0:57
  • 1
    Goto statements reduces throughput of cpu pipelining. It makes branch prediction hard,
    – CodeTalker
    Commented Jul 30, 2022 at 18:53
  • 1
    @CodeTalker so does any other statement that possibly exit the loop, whether is it goto, break, return... In practice this is not necessarily a big issue, as the branch that exits is executed only once after many executions of the branch that does not exit: any decent branch prediction algorithm will always predict the latter after a few iterations.
    – PierU
    Commented Apr 19, 2023 at 9:15
  • 1
    Does this answer your question? How to break out of nested loops? Commented Apr 27 at 12:13

20 Answers 20

356

No, don't spoil it with a break. This is the last remaining stronghold for the use of goto.

11
  • 39
    The MISRA C++ coding standard allows the use of goto to cover this exact kind of situation. Commented Aug 11, 2009 at 8:13
  • 41
    Real programmers are not afraid to use goto. Done it for 25 years -- no regrets -- saved a ton of development time.
    – Doug Null
    Commented Mar 22, 2016 at 19:02
  • 4
    I agree. gotos are a must if you do not have 8K pixels across, and need to call a sequence of 30 Windows OS calls. Commented Jun 16, 2017 at 15:21
  • 11
    Or a simple "return" by putting the code in a function.
    – Tara
    Commented Feb 8, 2019 at 3:32
  • 12
    I came here looking for a way out of a switch statement inside a while loop. Logically, that's only one level of looping, but switch eats the break. This is the first goto I've written since I was writing in BASIC, circa 1985. (It's a very "hot" loop, even checking an extra boolean each time around costs 15-20%, so adding a done flag is not a good option. I just had to write this comment to cleanse my soul.) Commented Jan 12, 2021 at 1:26
298

AFAIK, C++ doesn't support naming loops, like Java and other languages do. You can use a goto, or create a flag value that you use. At the end of each loop check the flag value. If it is set to true, then you can break out of that iteration.

13
  • 394
    Don't be afraid to use a goto if that is the best option.
    – jkeys
    Commented Aug 10, 2009 at 23:50
  • 29
    I'm a new C++ programmer (and one without any formal programming training) thus after reading about people's rants on goto. I'm hesitant on using it in fear my program might just suddenly explode and kill me. Other than that, when i used to write programs on my ti-83 (in boring math class of course), the functions the basic editor provided required the use of goto's.
    – Faken
    Commented Aug 11, 2009 at 2:18
  • 37
    @Faken: Two types of programmers use goto: Bad programmers, and pragmatic programmers. The former are self explanatory. The latter, which you would fit into if you choose to use them well, use a so called "evil" concept when it is the lesser of (two) evils. Read this for a better understanding of some C++ concepts that you might need to use from time to time (macros, goto's, preprocessor, arrays): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
    – jkeys
    Commented Aug 11, 2009 at 4:26
  • 52
    @Faken: There's nothing wrong with using goto. It's misusing a goto that is troublesome.
    – Everyone
    Commented Aug 11, 2009 at 4:51
  • 34
    @Hooked: That's right, except that using goto rarely ever is the best option. Why not put the loops into their own function (inline, if you're concerned about speed) and return from this?
    – sbi
    Commented Aug 11, 2009 at 9:08
132

Just to add an explicit answer using lambdas:

  for (int i = 0; i < n1; ++i) {
    [&] {
      for (int j = 0; j < n2; ++j) {
        for (int k = 0; k < n3; ++k) {
          return; // yay we're breaking out of 2 loops here
        }
      }
    }();
  }

Of course this pattern has a certain limitations and obviously C++11 only but I think it's quite useful.

7
  • 11
    This might confuse the reader into thinking the return causes the function the lambda is in to return, and not the lambda itself.
    – Xunie
    Commented Aug 25, 2016 at 1:55
  • 9
    @Xunie: If your loop is so complicated, that you forget that you are in a lambda, it is time to put them in a different function, but for simple cases, this should work quite well.
    – MikeMB
    Commented Dec 1, 2016 at 17:54
  • You can capture the lambda in a RIIA template that gives it a name and calls it in dtor(aka scope gaurd). This would not add any performance gain but can improve readabilty and reduce the risk of missing the function call parenthesis.
    – Red.Wave
    Commented Jun 15, 2018 at 6:42
  • this solution is not working when you also want a real return inside the loop... I mean: at one condition you just want to break out of 2 loops. at another condition you want to return out of the function. BTW: I really like this way of thinking! +1!
    – Thomas
    Commented Aug 13, 2020 at 9:51
  • 2
    I tested this on godbolt and it appears to compile to identical code to using a goto! Another advantage of this solution over goto is that labels only work if they label a statement. For example, you can't write my_label: }
    – Eyal
    Commented Feb 8, 2021 at 19:48
63

Another approach to breaking out of a nested loop is to factor out both loops into a separate function, and return from that function when you want to exit.

Of course, this brings up the other argument of whether you should ever explicitly return from a function anywhere other than at the end.

4
  • 8
    That's a C problem. With RIAA early return is not a problem as all the problems associated with early return are correctly handled. Commented Aug 11, 2009 at 0:12
  • 5
    I understand that proper application of RIAA can solve the resource cleanup problem in C++, but I have seen the philosophical argument against early return continue in other environments and languages. One system I worked on where the coding standard prohibited early return had functions littered with boolean variables (with names like continue_processing) that controlled the execution of blocks of code further down in the function. Commented Aug 11, 2009 at 0:23
  • 31
    What is RIAA? Is that anything like RAII? =D
    – jkeys
    Commented Aug 11, 2009 at 0:39
  • 2
    Depends how many for loops he's got and how deep the nest goes... do you want the blue pill or the red pill?
    – hookenz
    Commented Mar 24, 2014 at 4:16
38

break will exit only the innermost loop containing it.

You can use goto to break out of any number of loops.

Of course goto is often Considered Harmful.

is it proper to use the break function[...]?

Using break and goto can make it more difficult to reason about the correctness of a program. See here for a discussion on this: Dijkstra was not insane.

7
  • 22
    A good answer in that it explains that "goto is harmful" meme is strongly tied to the more generalized "control flow interruption is harmful" statement. It is meaningless to say "goto is harmful", and then turn around and recommend using break or return. Commented Aug 11, 2009 at 0:46
  • 7
    @Pavel: break and return have the advantage over goto that you don't need to hunt for a label in order to find where they go. Yes, underneath they are some kind of goto, but a very restricted one. They are a lot easier to decipher by a programmer's pattern-matching brain than the unrestricted goto. So IMO they are preferable.
    – sbi
    Commented Aug 11, 2009 at 9:13
  • 2
    @sbi: True, but break is still not part of structured programming. It is just better tolerated than a goto.
    – jkeys
    Commented Aug 11, 2009 at 15:53
  • 3
    @KarlVoigtland the Dijkstra link is outdated; this appears to be working: blog.plover.com/2009/07 Commented Feb 21, 2013 at 21:59
  • 9
    There is absolutely nothing wrong with using goto in this situation. A well placed goto is leaps and bounds better and more readable than many of the contorted solutions otherwise proposed.
    – James
    Commented Sep 19, 2013 at 13:07
36

How about this?

for(unsigned int i=0; i < 50; i++)
{
    for(unsigned int j=0; j < 50; j++)
    {
        for(unsigned int k=0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                j=50;
                k=50;
            }
        }
    }
}
1
  • 2
    interesting approach but I definitely like the way ered @inf.ig.sh handles it. for (unsigned int y = 0; y < y_max && !gotoMainLoop; y++).
    – Andrew
    Commented Jun 21, 2012 at 20:06
25

A code example using goto and a label to break out of a nested loop:

for (;;)
  for (;;)
    goto theEnd;
theEnd:
22

Although this answear was already presented, i think a good approach is to do the following:

for(unsigned int z = 0; z < z_max; z++)
{
    bool gotoMainLoop = false;
    for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
    {
        for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
        {
                          //do your stuff
                          if(condition)
                            gotoMainLoop = true;
        }
    }

}
4
  • 6
    which is good but still not so readable, i'd prefer goto in that case Commented Aug 28, 2013 at 17:03
  • 4
    this makes your code "quite" slow because the gotoMainLoop is checked every cycle
    – Thomas
    Commented Feb 4, 2016 at 17:52
  • 5
    In this case, using the real goto makes core more readable and better-performing. Commented Jan 25, 2017 at 17:16
  • This is slower, less readable, harder to write, just overall worse in every way, than using goto instead.
    – CPlus
    Commented May 7 at 18:03
16

I know this is an old thread but I feel this really needs saying and don't have anywhere else to say it. For everybody here, use goto. I just used it.

Like almost everything, goto is not 100% either/xor "bad" or "good". There are at least two uses where I'd say that if you use a goto for them - and don't use it for anything else - you should not only be 100% okay, but your program will be even more readable than without it, as it makes your intention that much clearer (there are ways to avoid it, but I've found all of them to be much clunkier):

  1. Breaking out of nested loops, and
  2. Error handling (i.e. to jump to a cleanup routine at the end of a function in order to return a failure code and deallocate memory.).

Instead of just dogmatically accepting rules like "so-so is 'evil'", understand why that sentiment is claimed, and follow the "why", not the letter of the sentiment. Not knowing this got me in a lot of trouble, too, to the point I'd say calling things dogmatically "evil" can be more harmful than the thing itself. At worst, you just get bad code - and then you know you weren't using it right so long as you heard to be wary, but if you are wracking yourself trying to satisfy the dogmatism, I'd say that's worse.

Why "goto" is called "evil" is because you should never use it to replace ordinary ifs, fors, and whiles. And why that? Try it, try using "goto" instead of ordinary control logic statements, all the time, then try writing the same code again with the control logic, and tell me which one looks nicer and more understandable, and which one looks more like a mess. There you go. (Bonus: try and add a new feature now to the goto-only code.) That's why it's "evil", with suitable scope qualification around the "evil". Using it to short-circuit the shortcomings of C's "break" command is not a problematic usage, so long as you make it clear from the code what your goto is supposed to accomplish (e.g. using a label like "nestedBreak" or something). Breaking out of a nested loop is very natural.

(Or to put it more simply: Use goto to break out of the loop. I'd say that's even preferable. Don't use goto to create the loop. That's "evil".)

And how do you know if you're being dogmatic? If following an "xyz is evil" rule leads your code to be less understandable because you're contorting yourself trying to get around it (such as by adding extra conditionals on each loop, or some flag variable, or some other trick like that), then you're quite likely being dogmatic.

There's no substitute for learning good thinking habits, moreso than good coding habits. The former are prior to the latter and the latter will often follow once the former are adopted. The problem is, however, that far too often I find, the latter are not explicated enough. Too many simply say "this is bad" and "this needs more thought" without saying what to think, what to think about, and why. And that's a big shame.

(FWIW, in C++, the need to break out of nested loops still exists, but the need for error codes does not: in that case, always use exceptions to handle error codes, never return them unless it's going to be so frequent that the exception throw and catch will be causing a performance problem, e.g. in a tight loop in a high demand server code, perhaps [some may say that 'exceptions' should be 'used rarely' but that's another part of ill-thought-out dogmatism: no, at least in my experience after bucking that dogma I find they make things much clearer - just don't abuse them to do something other than error handling, like using them as control flow; effectively the same as with "goto". If you use them all and only for error handling, that's what they're there for.].)

13

One nice way to break out of several nested loops is to refactor your code into a function:

void foo()
{
    for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < 50; j++)
        {
            for(unsigned int k=0; k < 50; k++)
            {
                // If condition is true
                return;
            }
        }
    }
}
6
  • 4
    ...which is not a option if we have to pass 10-20 variables for stack framing this function. Commented Aug 28, 2013 at 17:04
  • 1
    @ПетърПетров then go for a lambda which is also better as you can define it exactly where you need it.
    – DarioP
    Commented Nov 7, 2013 at 13:28
  • 2
    +1 for lambdas but overhaul in game engine core where even one stack frame is still a bottleneck. Sorry to tell, but lambdas are not so lightweight at least in MSVC 2010. Commented Apr 9, 2014 at 13:12
  • @ПетърПетров Then change the pair of functions into a class, and the stack variables into private members. Commented Nov 10, 2017 at 13:25
  • 2
    This only overcomplicates the already complex code :) Sometimes, goto is the only solution. Or if you write complex automata with "goto state X" documentation, then goto is actually making the code read as written in the document. Also, C# and go both have goto with a purpose: no language is turing-complete without a goto, and gotos are often the best used tools for writing intermediate translator or assembly-like code. Commented Dec 1, 2017 at 14:35
11

I'm not sure if it's worth it, but you can emulate Java's named loops with a few simple macros:

#define LOOP_NAME(name) \
    if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
    { \
        [[maybe_unused]] CAT(_namedloop_break_,name): break; \
        [[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
    } \
    else

#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)

#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y

Example usage:

#include <iostream>

int main()
{
    // Prints:
    // 0 0
    // 0 1
    // 0 2
    // 1 0
    // 1 1

    for (int i = 0; i < 3; i++) LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << i << ' ' << j << '\n';
            if (i == 1 && j == 1)
                BREAK(foo);
        }
    }
}

Another example:

#include <iostream>

int main()
{
    // Prints: 
    // 0
    // 1
    // 0
    // 1
    // 0
    // 1

    int count = 3;
    do LOOP_NAME(foo)
    {
        for (int j = 0; j < 3; j++)
        {
            std::cout << ' ' << j << '\n';
            if (j == 1)
                CONTINUE(foo);
        }
    }
    while(count-- > 1);
}
7
  • Although, it seems to let the outer loop to finish its current routine. It also doesn't directly "jump over" multiple levels of nested loops.
    – radrow
    Commented Jul 14, 2022 at 13:06
  • @radrow Can you show an example of the wrong behavior? Seems to work correctly for me. Commented Jul 14, 2022 at 13:33
  • Nevermind, I tested it and it works perfectly indeed. However, an explanation on how it works would be useful :)
    – radrow
    Commented Jul 15, 2022 at 9:51
  • 1
    @radrow There's not much to see here, once you expand the macros and look at the result. The loop body becomes if (false) {...} else {/*original loop body*/}, where the first branch that's never taken contains a few goto labels, that BREAK and CONTINUE jump to. Commented Jul 15, 2022 at 10:09
  • 2
    @Dumbled0re The variable is needed to stop you from using break/continue outside of this loop. The compiler refuses to goto into a scope if it requires creating a new variable, allowing you to break/continue only inside this if-else block. Commented Jul 25, 2022 at 18:29
7

goto can be very helpful for breaking nested loops

for (i = 0; i < 1000; i++) {
    for (j = 0; j < 1000; j++) {
        for (k = 0; k < 1000; k++) {
             for (l = 0; l < 1000; l++){
                ....
                if (condition)
                    goto break_me_here;
                ....
            }
        }
    }
}

break_me_here:
// Statements to be executed after code breaks at if condition
5

I do think a goto is valid in this circumstance:

To simulate a break/continue, you'd want:

Break

for ( ;  ;  ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            goto theEnd;
        }
    }
}
theEnd:

Continue

for ( ;  ; ) {
    for ( ;  ;  ) {
        /*Code here*/
        if (condition) {
            i++;
            goto multiCont;
        }
    }
    multiCont:
}
2
  • "Continue" will not work there, because the iteration expression of the first loop won't be executed
    – Fabio A.
    Commented Feb 22, 2017 at 17:09
  • I'm assuming that the iterator for the first loop is i. Hence i++ before the goto Commented Jul 2, 2018 at 8:46
3

The break statement terminates the execution of the nearest enclosing do, for, switch, or while statement in which it appears. Control passes to the statement that follows the terminated statement.

from msdn.

2

My suggestion is use a check variable to break a desired loop. The result code may not be so pleasant.
You can use preprocessors in order to make desired breaking under the hood. This approach can hides ugly codes and extra complexity.
For example, I created my custom break mechanism as follow:

Wanted code:

for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 100; k++) {
            //do something
            if (desiredCondition) {
                breakToLevel = 0;
            }
            if (breakToLevel < 3) {
                break;
            }
        }
        if (breakToLevel < 2) {
            break;
        }
    }
    if (breakToLevel < 1) {
        break;
    }
}

Defined macros:

#define BREAK_TO(L) breakToLevel = (L); 
#define CHECK_BREAK(L) if (breakToLevel < (L)) break; 

and result:

for (int i = 0; i < 100; i++) {
    for (int j = 0; j < 100; j++) {
        for (int k = 0; k < 100; k++) {
            //do something
            if (desiredCondition) {
                BREAK_TO(0)
            }
            CHECK_BREAK(3)
        }
        CHECK_BREAK(2)
    }
    CHECK_BREAK(1)
}
0

You will have to work it out by using a boolean that you set to false prior to the loop, set to true in the loop if you want to break, plus a conditional break after the nested loop, checking if the boolean was set to true and break if yes.

1
  • Why would you check a flag every iteration if there are so many better options? So the statement that you will 'have' to is wrong. Also this 'solution' was also mentioned in the accepted answer so this is redundant.
    – CPlus
    Commented Jul 19 at 0:55
-1

I know this is old post . But I would suggest a bit logical and simpler answer.

for(unsigned int i=0; i < 50; i++)
    {
        for(unsigned int j=0; j < conditionj; j++)
        {
            for(unsigned int k=0; k< conditionk ; k++)
            {
                // If condition is true

                j= conditionj;
               break;
            }
        }
    }
2
  • 5
    That's not very scalable solution as j = conditionj won't work if you have a complex predicate instead of j < conditionj.
    – Sergey
    Commented Sep 14, 2016 at 16:01
  • This is really error prone, if someone changes conditionj only only for the for statement, then bad things can happen...
    – Cristik
    Commented May 10 at 13:00
-1

Break any number of loops by just one bool variable see below :

bool check = true;

for (unsigned int i = 0; i < 50; i++)
{
    for (unsigned int j = 0; j < 50; j++)
    {
        for (unsigned int k = 0; k < 50; k++)
        {
            //Some statement
            if (condition)
            {
                check = false;
                break;
            }
        }
        if (!check)
        {
            break;
        }
    }
    if (!check)
    {
        break;
    }
}

In this code we break; all the loops.

1
  • One extra check for every single iteration is much slower and more inefficient. I would take a simple goto over this any day.
    – CPlus
    Commented May 7 at 17:49
-1

The most graceful way is to use exception.

Exception means encountering an abnormal situation, which can not only be a too bad situation but also be a too good situation.

For example you are looking for an element in a 3d array with 3 nested for-loops. The normal situation is "The current is NOT the one I'm looking for". The abnormal situation is "The current IS the one".

Remember the difference between error and exception. An exception doesn't have to be an error, it can be a good news.

-3

You can use try...catch.

try {
    for(int i=0; i<10; ++i) {
        for(int j=0; j<10; ++j) {
            if(i*j == 42)
                throw 0; // this is something like "break 2"
        }
    }
}
catch(int e) {} // just do nothing
// just continue with other code

If you have to break out of several loops at once, it is often an exception anyways.

8
  • 10
    @hkBattousai The solution has down votes because it's using an exception to control the execution flow. As the name suggests, exceptions should only be used on exceptional cases. Commented Jun 18, 2015 at 21:07
  • 4
    @HelioSantos Isn't this an exceptional situation for which the language is not supplying proper solution? Commented Jun 21, 2015 at 11:14
  • 4
    The performance impact of the throw is huge for something that is not an unrecoverable error 99% of the time. Commented Jun 16, 2017 at 5:24
  • 4
    @hkbattousai The language does provide solutions, such as using a a test condition, or using a goto. Commented Jun 17, 2017 at 21:17
  • 2
    Also, if another exception was thrown from that code block, you would catch it, thinking it is the control flow one and it would get propagated/handled properly.
    – John Smith
    Commented Apr 26, 2018 at 20:06

Not the answer you're looking for? Browse other questions tagged or ask your own question.