Sign in to follow this  
Norman Barrows

C++ best way to break out of nested for loops

Recommended Posts

C++    best way to break out of nested for loops

 

 

for a ......

    for b .....

         if (some_condition)

              // break out of both loops

 

 

 

 

a break will get you out of the inner loop.

 

but i think only goto will get you out of both, without returning that is.

 

 

Share this post


Link to post
Share on other sites


Or break the algorithm out into it's own function and use return.

 


return always seems cleanest to me.

 

yeah, that's what i usually do.

 

but its just a stupid little nested loop to iterate over a collision map and find the first passable node for use as a test goal for the new A* code in Caveman 3.0.

 

i'll make it a function call with return.

 

its faster than looking up goto syntax, and cleaner than stuffing it into the for() statement.

 

some "patterns" never change, eh?

Share this post


Link to post
Share on other sites

Lol yeah you'd never write either of those two bits of code, hopefully  :lol:

The lambda syntax comes in handy when you want to reuse a bit of code, but don't want to bother actually breaking it out into it's own independent function, yet. e.g.

void test()
{
  int sum = 0;
  auto SumArray = [&](int* data, int size){
    for( int i=0; i!=size; ++i )
      sum += data[i];
  };
  for( int widgetIdx=0; widgetIdx != numWidgets; ++widgetIdx )
    SumArray( widgets[widgetIdx].data, widgets[widgetIdx].size );
  SumArray( specialWidget.data, specialWidget.size );
  printf( "%d\n", sum );
}

which is shorthand for:

void test()
{
  int sum = 0;
  struct _ { _(int& sum):sum(sum){}int& sum;
    void operator()(int* data, int size){
      for( int i=0; i!=size; ++i )
        sum += data[i];
    };
  }SumArray(sum);
  for( int widgetIdx=0; widgetIdx != numWidgets; ++widgetIdx )
    SumArray( widgets[widgetIdx].data, widgets[widgetIdx].size );
  SumArray( specialWidget.data, specialWidget.size );
  printf( "%d\n", sum );
}

or the more obvious, actually breaking it out into it's own separate function:

namespace { void SumArray(int* data, int size, int& sum){
  for( int i=0; i!=size; ++i )
    sum += data[i];
};}
void test()
{
  int sum = 0;
  for( int widgetIdx=0; widgetIdx != numWidgets; ++widgetIdx )
    SumArray( widgets[widgetIdx].data, widgets[widgetIdx].size, sum );
  SumArray( specialWidget.data, specialWidget.size, sum );
  printf( "%d\n", sum );
}

Share this post


Link to post
Share on other sites

 

some "patterns" never change, eh?

We get new tools though :)
void test()
{
  printf( "start\n" );
  for( int x=0; x!=10; ++x )
    for( int y=0; y!=10; ++y )
      if( x == y && x == 5 )
        goto double_break;
      else
        printf( "%d, %d\n", x, y );
  double_break:
  printf( "end\n" );
}
In 2016 can be written as:
void test()
{
  printf( "start\n" );
  [](){
  for( int x=0; x!=10; ++x )
    for( int y=0; y!=10; ++y )
      if( x == y && x == 5 )
        return;
      else
        printf( "%d, %d\n", x, y );
  }();
  printf( "end\n" );
}

Did not realize you could invoke the lambda at its definition.

 

"its faster than looking up goto syntax"

If you've ever written a goto, how could you possibly need to look up the syntax? 

 

I'd be looking up the break syntax if anything, to see if C++ features labeled breaks yet.

Share this post


Link to post
Share on other sites

Put it in the loop statement rather than use break.

for( a = a_init; a != a_end && !condition; a = a_next )
  for( b = b_init; b != b_end && !condition; b = b_next )
    ...

Or break the algorithm out into it's own function and use return.

A billion times this. Putting the extra condition in the loop is clean and easy to understand.

If you've got a deeply nested loop, you may have to rethink what you're doing instead of blaming the language. If impossible to refactor, breaking the algo into several functions is a perfectly valid strategy. Gets easier to grok, may even reveal more info thanks to isolation and dependencies thanks to the function arguments being passed.

Share this post


Link to post
Share on other sites

A billion times this. Putting the extra condition in the loop is clean and easy to understand.


You can't break in the middle of a block though:

 

doSomething ();

if (condition) break;

doSomethingElse ();

 

Well you could, by introducing an else, but then you're starting to lose clarity.  On balance, return is absolutely unambiguous about what the programmer's intentions are and has the lowest associated risk if someone revisits the code in 6 months and tries to get too clever with it.

Share this post


Link to post
Share on other sites

This is one of a handful of cases where goto is still relevant. As was already mentioned, break is just a special case of goto.

You could use a lamda and return instead, but a good compiler is going to produce identical machine code for both cases, and it doesn't provide a readability benefit.

Hope C++17 adds break N like in PHP. would be nice.

Edited by nfries88

Share this post


Link to post
Share on other sites

You can use lambda. You create inline lambda, make it capture everything by reference with [&] and call it immediately.

When you call return, you will return from whole lambda.

// some preceding code

// our double loop
[&]()
{
   for a ......
      for b .....
         if (some_condition)
            return;
}(); // calling lambda immediately

// some following code
Edited by Ivorne

Share this post


Link to post
Share on other sites

I'd just break it out into a separate function, to be honest.  The compiler's going to inline it anyway if it determines that there's a perf benefit, and in the event that I ever need the code twice, the work is already done for me.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this