374

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?

Peter Mortensen
  • 30,030
  • 21
  • 100
  • 124
Faken
  • 10,602
  • 16
  • 56
  • 73
  • 8
    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. – Rishab Shinghal Aug 26 '19 at 13:49
  • 2
    why goto is bad programming practice? it's widely used in kernel. – Alexis Feb 23 '22 at 00:57

21 Answers21

314

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

Henk Holterman
  • 250,905
  • 30
  • 306
  • 490
  • 30
    The MISRA C++ coding standard allows the use of goto to cover this exact kind of situation. – Richard Corden Aug 11 '09 at 08:13
  • 26
    Real programmers are not afraid to use goto. Done it for 25 years -- no regrets -- saved a ton of development time. – Doug Null Mar 22 '16 at 19:02
  • 2
    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. – Michaël Roy Jun 16 '17 at 15:21
  • 3
    Or a simple "return" by putting the code in a function. – Tara Feb 08 '19 at 03:32
  • 5
    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.) – Jim Pivarski Jan 12 '21 at 01:26
  • I think it's a myth that using goto is bad. Also for the resulting machine code it's no difference if you use while, for, break, return or goto. It will all be translated into jumps... – somega May 17 '22 at 09:15
283

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.

Cullen Walsh
  • 4,208
  • 1
  • 15
  • 12
  • 371
    Don't be afraid to use a `goto` if that is the best option. – jkeys Aug 10 '09 at 23:50
  • 28
    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 Aug 11 '09 at 02:18
  • 2
    I seem to remember reading that many compilers give up on optimizing loops when a goto is present... – Steven Sudit Aug 11 '09 at 02:41
  • 34
    @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): http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15 – jkeys Aug 11 '09 at 04:26
  • 46
    @Faken: There's nothing wrong with using goto. It's _misusing_ a goto that is troublesome. – Everyone Aug 11 '09 at 04: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 Aug 11 '09 at 09:08
  • 7
    @sbi, sometime our functions have very big stack frame, and passing about 9-10+ vars will definetly make our code unreadable. Take a break and use goto, in this case it makes your program sexier and more readable. Some algorithms have sooo much control paths that makes goto more preferred way, especially state mashines in game loop - performance critical code where even a simple stack frame losses most or your performance! – Петър Петров Aug 28 '13 at 16:58
  • 3
    @ПетърПетров inlined functions don't have a stack frame – Tim Seguine Nov 04 '13 at 11:42
  • 5
    inline is a compiler hint keyword, no guarantee it will inline the function. In any case, you write the code as though they were not inline which means passing variables.... I'm with @Петър Петров on that. – hookenz Mar 24 '14 at 04:14
  • 1
    Unfortunately, I ended up seeing with my eyes how a stack frame was initialized on calling a inline function. Compiler have its final decision on that. The only really inlined thing is a macro. In fact, compiler will not even see it :) And DO NOT BOTHER throwing! It's like calling "goto" 10000 times in a row. – Петър Петров Apr 09 '14 at 13:05
  • 1
    If the function manipulates 9-10+ variables within a loop, the performance penalty of that creation of the stack frame is absolutely negligible. – Marian Spanik Nov 23 '15 at 21:16
  • 2
    Creating - and unwinding - a Stack Frame is more expensive than checking flag then performing a jump. `if...goto` very often gets compiled to to `je` or `jne` local jumps pair, while the `call` / `ret` function semantic often does far jumps and cache misses. So, don't be afraid to use `goto` it is is the smaller evil of twos. And, _never_ truse `inline` if you want speed. – Петър Петров Jan 25 '17 at 17:09
115

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.

Predelnik
  • 4,893
  • 2
  • 23
  • 36
  • 9
    This might confuse the reader into thinking the return causes the function the lambda is in to return, and not the lambda itself. – Xunie Aug 25 '16 at 01:55
  • 6
    @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 Dec 01 '16 at 17:54
  • 35
    I think this solution is beautiful – tuket Aug 24 '17 at 10:55
  • 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 Jun 15 '18 at 06: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 Aug 13 '20 at 09: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 Feb 08 '21 at 19:48
  • How this is called? First time to see it in code. – Alexis Feb 23 '22 at 00:59
62

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.

Greg Hewgill
  • 890,778
  • 177
  • 1,125
  • 1,260
  • 7
    That's a C problem. With RIAA early return is not a problem as all the problems associated with early return are correctly handled. – Martin York Aug 11 '09 at 00:12
  • 4
    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. – Greg Hewgill Aug 11 '09 at 00:23
  • 26
    What is RIAA? Is that anything like RAII? =D – jkeys Aug 11 '09 at 00: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 Mar 24 '14 at 04:16
37

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.

Mitja
  • 1,910
  • 31
  • 33
Karl Voigtland
  • 7,437
  • 32
  • 29
  • 18
    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`. – Pavel Minaev Aug 11 '09 at 00: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 Aug 11 '09 at 09:13
  • 2
    @sbi: True, but break is still not part of structured programming. It is just better tolerated than a `goto`. – jkeys Aug 11 '09 at 15:53
  • 2
    @KarlVoigtland the Dijkstra link is outdated; this appears to be working: http://blog.plover.com/2009/07/ – Aaron Brager Feb 21 '13 at 21:59
  • 5
    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 Sep 19 '13 at 13:07
  • I'd argue that C++'s "goto after_loop;" is so straightforward it's easier to understand than Java's "break before_loop;". I don't find it particularly elegant to quit a loop by referring to a label that's declared before the actual loop. I know the label is supposed to give the loop a name, but I never managed to like it. What if you put other statements between the label and the loop? Is that a syntax error to try to break? Same for continue statements. – Johan Boulé Feb 10 '21 at 19:14
34

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;
            }
        }
    }
}
jebeaudet
  • 1,363
  • 13
  • 15
  • 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 Jun 21 '12 at 20:06
22

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

for (;;)
  for (;;)
    goto theEnd;
theEnd:
Helio Santos
  • 6,328
  • 3
  • 24
  • 30
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;
        }
    }

}
scigor
  • 1,584
  • 5
  • 23
  • 38
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;
            }
        }
    }
}
Deqing
  • 12,998
  • 13
  • 78
  • 120
  • 4
    ...which is not a option if we have to pass 10-20 variables for stack framing this function. – Петър Петров Aug 28 '13 at 17:04
  • 1
    @ПетърПетров then go for a lambda which is also better as you can define it exactly where you need it. – DarioP Nov 07 '13 at 13:28
  • +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. – Петър Петров Apr 09 '14 at 13:12
  • @ПетърПетров Then change the pair of functions into a class, and the stack variables into private members. – Arthur Tacca Nov 10 '17 at 13:25
  • 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. – Петър Петров Dec 01 '17 at 14:35
  • @ПетърПетров If you have to pass 20 stack variables I'd argue there are bigger problems than the choice of `return` vs. `goto`. – c z Jun 01 '21 at 11:34
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
7

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.].)

The_Sympathizer
  • 1,019
  • 9
  • 15
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.

Rob
  • 2,148
  • 13
  • 17
3

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:
}
3

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);
}
HolyBlackCat
  • 63,700
  • 7
  • 105
  • 170
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.

Vikas Bansal
  • 1,350
  • 13
  • 17
0

Other languages such as PHP accept a parameter for break (i.e. break 2;) to specify the amount of nested loop levels you want to break out of, C++ however doesn't. 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.

Patrick Glandien
  • 7,601
  • 5
  • 39
  • 47
0

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;
            }
        }
    }
  • 3
    That's not very scalable solution as `j = conditionj` won't work if you have a complex predicate instead of `j < conditionj`. – Sergey Sep 14 '16 at 16:01
0
 bool found = false;
    
    for(int i=0; i < m; ++i){
        for(int j=0; j < n; ++j)
            if(grid[i][j] == '*'){
                q.push(make_pair(i,j));
                found = true;
                break;
            }
        if(found)
            break;
    }
-1
  while (i<n) {
    bool shouldBreakOuter = false;
    for (int j=i + 1; j<n; ++j) {
      if (someCondition) {
          shouldBreakOuter = true;
      }
    }

    if (shouldBreakOuter == true)
      break;

  }
MEnnabah
  • 2,015
  • 1
  • 18
  • 38
-2

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.

lawilog
  • 173
  • 6
  • 1
    I would like to know the reason why this answer get this much down-votes. – hkBattousai Jun 18 '15 at 13:10
  • 6
    @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. – Helio Santos Jun 18 '15 at 21:07
  • 4
    @HelioSantos Isn't this an exceptional situation for which the language is not supplying proper solution? – hkBattousai Jun 21 '15 at 11:14
  • It would be valid if 1. my program is compiled with exceptions support (never in my case) and 2. it really WAS an exception 3. You are willing to put up with the horrific overhead. – Lennart Rolland Jan 04 '17 at 12:01
  • 2
    The performance impact of the throw is huge for something that is not an unrecoverable error 99% of the time. – Michaël Roy Jun 16 '17 at 05:24
  • 1
    @hkbattousai The language does provide solutions, such as using a a test condition, or using a `goto`. – Michaël Roy Jun 17 '17 at 21:17
  • 1
    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 Apr 26 '18 at 20:06
-5

Breaking out of a for-loop is a little strange to me, since the semantics of a for-loop typically indicate that it will execute a specified number of times. However, it's not bad in all cases; if you're searching for something in a collection and want to break after you find it, it's useful. Breaking out of nested loops, however, isn't possible in C++; it is in other languages through the use of a labeled break. You can use a label and a goto, but that might give you heartburn at night..? Seems like the best option though.

Nick Lewis
  • 4,106
  • 1
  • 19
  • 22
  • 11
    It's not strange at all. If you're iterating over a collection to look for something (and don't have a faster way of searching), there's no point finishing the loop. (as one example) – Joe Aug 11 '09 at 00:44