Search

Enter your search terms

Submit search form

5.8 — Break and continue

By Alex on June 26th, 2007 | last modified by Alex on August 23rd, 2016

Break

Although you have already seen the break statement in the context of switch statements, it deserves a fuller treatment since it can be used with other types of loops as well. The break statement causes a do, for, switch, or while statement to terminate.

Breaking a switch

In the context of a switch statement, a break is typically used at the end of each case to signify the case is finished (which prevents fall-through):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

switch(ch)

{

case'+':

doAddition(x,y);

break;

case'-':

doSubtraction(x,y);

break;

case'*':

doMultiplication(x,y);

break;

case'/':

doDivision(x,y);

break;

}

Breaking a loop

In the context of a loop, a break statement can be used to cause the loop to terminate early:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

#include <iostream>

intmain()

{

intsum=0;

// Allow the user to enter up to 10 numbers

for(intcount=0;count<10;++count)

{

std::cout<<"Enter a number to add, or 0 to exit: ";

intnum;

std::cin>>num;

// exit loop if user enters 0

if(num==0)

break;

// otherwise add number to our sum

sum+=num;

}

std::cout<<"The sum of all the numbers you entered is "<<sum<<"\n";

return0;

}

This program allows the user to type up to 10 numbers, and displays the sum of all the numbers entered at the end. If the user enters 0, the break causes the loop to terminate early (before 10 numbers have been entered).

Note that break can be used to get out of an infinite loop:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

#include <iostream>

intmain()

{

while(true)// infinite loop

{

std::cout<<"Enter 0 to exit or anything else to continue: ";

intnum;

std::cin>>num;

// exit loop if user enters 0

if(num==0)

break;

}

std::cout<<"We're out!\n";

return0;

}

Break vs return

New programmers often have trouble understanding the difference between break and return. A break statement terminates the switch or loop, and execution continues at the first statement beyond the switch or loop. A return statement terminates the entire function that the loop is within, and execution continues at point where the function was called.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include <iostream>

intbreakOrReturn()

{

while(true)// infinite loop

{

std::cout<<"Enter 'b' to break or 'r' to return: ";

charch;

std::cin>>ch;

if(ch=='b')

break;// execution will continue at the first statement beyond the loop

if(ch=='r')

return1;// return will cause the function to immediately return to the caller (in this case, main())

}

// breaking the loop causes execution to resume here

std::cout<<"We broke out of the loop\n";

return0;

}

intmain()

{

intreturnValue=breakOrReturn();

std::cout<<"Function breakOrContinue returned "<<returnValue<<'\n';

return0;

}

Continue

The continue statement provides a convenient way to jump to the end of the loop body for the current iteration. This is useful when we want to terminate the current iteration early.

Here’s an example of using continue:

1

2

3

4

5

6

7

8

9

10

11

for(intcount=0;count<20;++count)

{

// if the number is divisible by 4, skip this iteration

if((count%4)==0)

continue;// jump to end of loop body

// If the number is not divisible by 4, keep going

cout<<count<<endl;

// The continue statement jumps to here

}

This program prints all of the numbers from 0 to 19 that aren’t divisible by 4.

In the case of a for loop, the end-statement of the for loop still executes after a continue (since this happens after the end of the loop body).

Be careful when using a continue statement with while or do-while loops. Because these loops typically increment the loop variables in the body of the loop, using continue can cause the loop to become infinite! Consider the following program:

1

2

3

4

5

6

7

8

9

10

intcount(0);

while(count<10)

{

if(count==5)

continue;// jump to end of loop body

cout<<count<<" ";

++count;

// The continue statement jumps to here

}

This program is intended to print every number between 0 and 9 except 5. But it actually prints:

0 1 2 3 4

and then goes into an infinite loop. When count is 5, the if statement evaluates to true, and the loop jumps to the bottom. The count variable is never incremented. Consequently, on the next pass, count is still 5, the if statement is still true, and the program continues to loop forever.

Here’s an example with a do-while loop using continue correctly:

1

2

3

4

5

6

7

8

9

intcount(0);

do

{

if(count==5)

continue;// jump to end of loop body

cout<<count<<" ";

// The continue statement jumps to here

}while(++count<10);// this still executes since it's outside the loop body

This prints:

0 1 2 3 4 6 7 8 9

Using break and continue

Many textbooks caution readers not to use break and continue, both because it causes the execution flow to jump around and because it can make the flow of logic harder to follow. For example, a break in the middle of a complicated piece of logic could either be missed, or it may not be obvious under what conditions it should be triggered.

However, used judiciously, break and continue can help make loops more readable by keeping the number of nested blocks down and reducing the need for complicated looping logic.

For example, consider the following program:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

#include <iostream>

intmain()

{

intcount(0);// count how many times the loop iterates

boolexitLoop(false);// controls whether the loop ends or not

while(!exitLoop)

{

std::cout<<"Enter 'e' to exit this loop or any other key to continue: ";

charch;

std::cin>>ch;

if(ch=='e')

exitLoop=true;

else

{

++count;

std::cout<<"We've iterated "<<count<<" times\n";

}

}

return0;

}

This program uses a boolean variable to control whether the loop continues or not, as well as a nested block that only runs if the user doesn’t exit.

Here’s a version that’s easier to understand, using a break statement:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

#include <iostream>

intmain()

{

intcount(0);// count how many times the loop iterates

while(true)// loop until user terminates

{

std::cout<<"Enter 'e' to exit this loop or any other key to continue: ";

charch;

std::cin>>ch;

if(ch=='e')

break;

++count;

std::cout<<"We've iterated "<<count<<" times\n";

}

return0;

}

In this version, by using a single break statement, we’ve avoided the use of a boolean variable (and having to understand both what its intended use is, and where it is set), an else statement, and a nested block.

Minimizing the number of variables used and keeping the number of nested blocks down both improve code understandability more than a break or continue harms it. For that reason, we believe judicious use of break or continue is acceptable.

Since the message asks the user to enter a character and a newline is not considered a character (by a non-coder user) I'd say the behavior is correct. You can press enter as much as you want until you enter a character.

If you want to continue when enter is pressed even without a character having been entered before you can use std::cin.peek in combination with std::cin.ignore

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

#include <iostream>

#include <limits> // For std::numeric_limits

intmain()

{

intcount{0};

while(true)

{

std::cout<<"Enter 'e' to exit this loop or any other key to continue: ";

// Get the next character in the input stream. If the user presses enter @ch

Under the section "Using break and continue" I see that char ch is defined within the while loop. Could you say something about the creation and destruction of this variable each time through the while loop? Put another way, is there an efficiency saving if the variable is created outside the while loop?

For native data types (int, char, float, etc.) there is no difference between creating it inside or outside the loop. This is the case, because those data types fit into a single register (A variable that has always and will always exist and never gets constructed or destructed). So that @ch variable doesn't really exist, instead, a register will be used.
For complex data types there could be a performance difference. Classes haven't been covered yet so there's no point in trying to explain what causes this. But basically, if the class (Data type) is written properly there shouldn't be a difference here either.

(Also see the reply to your reply in the following comment)
There are only so many registers and different compilers and machines will do things differently. I agree that in the simple example, there will almost certainly be no difference. My problem is, "what in general should I do in practice if I have the goal of trying to write efficient code?" I might very well not know where or how the code I write might be used in the future. Wouldn't it make sense to, at least by default, try to "communicate" with the compiler by indicating that a variable should be created outside of a loop (assuming this is possible because of the program logic)? I would think that should generally lead to more efficient code even for less optimizing compilers or situations where the compiler is struggling with lots of variables, arrays, structures, objects, et cetera. Your thoughts on this?

Scenario 1, Variable created outside of the loop, all registers are taken:
- One of the used registers will be pushed onto the stack
- Your variable uses that register
- Loop finishes, the original register is popped and restored

Scenario 2, Variable created inside of the loop, all registers are taken:
(It's the same)
- One of the used registers will be pushed onto the stack
- Your variable uses that register
- Loop finishes, the original register is popped and restored

Now you might say, "ok, it doesn't matter what I do then", wrong!
Scenario 1 leaves you with one occupied identifier (The name of the variable) that can no longer be used after the loop.

This is one of the things that the compiler knows best. So you choose the option that's better for your code, and that is, keeping your variables in the smallest scope possible.

Well, in scenario 2, it may mean pushing a register at each iteration, a significant difference from scenario 1. Even more of a problem for larger data structures.

Regarding re-use of identifier names: that was an issue covered elsewhere. I think it is more of what people are used to and the kind of algorithms that are tackled. There are places for each style and the main thing is to understand the pros and cons.

Thank you so much for your reply. I see you have helped lots of people in these comment sections; your assistance is greatly appreciated.

I figured out how to disassemble code under Visual Studio and it looks like the code doesn't even use exitLoop at all. The branch is after a compare with 'e'.

Who knows what different compilers are going to do? What does this mean in practice for a programmer who wants to write efficient code? My approach has been to try to "suggest" to the compiler what I can that might lead to efficiencies. That would mean, for example, minimizing operations and using operations that I determined executed quickly. How do you approach this issue?

The compiler usually knows best. You can try to improve little things like these in code but after compilation it will most likely be the same.
If you want to gain performance you should search for loops where you might be running a needles iteration, parameters that you're passing by value even though they're of non-standard size, poorly written algorithms, and so on.
So as long as you're code in efficient when evaluating it by hand, it will be efficient when it's compiled and executed by your computer.

I think the last example about break might be a little misleading because the break happens before the last print statement meaning that the loop was terminated before executing this print statement. with the bool, when you set it to true it executes the rest of the loop THEN it terminates. these two examples are similar, but don't produce the same output. (I think. Forgive me if I'm wrong). Is this right?

They do produce the same output (easily verifiable by running them). In the non-break case, if the user enters 'e' the rest of the loop body is skipped because it's inside an else block that does not execute for that iteration.

In this program I do not understand how setting exitloop = true makes the while loop break. If bool exitLoop(false) and then in the while loop it's set to !exitLoop, wouldn't that make it true? So when it reaches the if statement exitloop = true, and wouldn't that imply that pressing "e" would keep the while loop going?
int main()
{
int count(0); // count how many times the loop iterates
bool exitLoop(false); // controls whether the loop ends or not
while (!exitLoop)
{
std::cout << "Enter 'e' to exit this loop or any other key to continue: ";
char ch;
std::cin >> ch;

Nope. Your while condition is on (!exitLoop). This means you'll keep looping as long as !exitLoop is true, which is equivalent to when exitLoop is false.

Since exitLoop starts as false, your loop will keep looping until you hit the if (ch=='e') statement and that sets exitLoop to true. At that point, !exitLoop evaluates to false, so the loop will not iterate.

Alex, one suggestion, but please feel free to check if it's appropriate.

When explaining "continue" statement on for loops, you say:
"The continue statement provides a convenient way to jump back to the loop conditional earlier than normal, which can be used to bypass the remainder of the loop for an iteration."

Although this is true, I'd emphasize that on a for loop, continue won't jump directly to the conditional, but rather, before that, executes the "end statement". This get's clear when you explain the caveats of using continue on while and do-while.

I'd use:
"The continue statement provides a convenient way to jump back to the end-statement and loop conditional earlier than normal...".

ps.: brilliant comparison of a for loop and while construct. Simple but spot on.

I disagree with the use of break in the while loop. There is probably always a way to re-organise your code to remove any break or continue usage within a loop. For example, the code in your final example could be written with a do-while construct:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#include <iostream>

intmain(){

charch;

intcount(0);// count how many times the loop iterates

do{

std::cout<<"We've iterated "<<++count<<" times\n";

std::cout<<"Enter 'e' to exit this loop or any other key to keep looping\n";

std::cin>>ch;

}while(ch!='e');

return0;

}

Now admittedly this will print the first iteration output but it does gives you access to the character variable outside of the loop, which is something you probably want for a larger program. But arguing against my own point if break or continue do make the code easier to read, and there is no other legitimate way of doing things, then maybe they can be used. But with comments as to why.

To me, it's cleaner to explicitly break the loop than have char ch declared outside the loop and exposed beyond it (then I have to worry about whether it does anything -- I like my variables to go out of scope as soon as they're no longer needed).

There are definitely people who share your opinion -- and the related opinion that functions shouldn't ever have an early return (only one return at the bottom). I disagree with that general philosophy. You should do whatever makes your code easiest to understand and maintain -- and often (but not always), use of break, continue, or return is the best choice for that.

Fair point. I'm in complete agreement that code readability and code maintainability are paramount when programming.

My point was that the example you gave was contrived to read better once you'd factored in the break, that doesn't mean having a break (or continue) will necessarily make your code more clear; I think we're in agreement on that point. In my opinion if it is logical and performant to do so an early return statement is fine so long as the intent and outcome is clear, and commented if not.

I'm not sure why C++ doesn't support this, as there are certainly cases where it would be useful to break out of any arbitrary block. There are a number of workarounds but none of them are great, as they obfuscate the intent of the programmer.

Buddy, I think it is a problem with the comment formatter or something of this site, because your comment too is showing 'n-' where you intended 'n - -'. I've seen it in other comments too. Even Alex seems to be experiencing such issues (with angle brackets, IIRC).

It would be safer to put all our code inside the syntax highlighter using the [code] tags, which displays them alright. To type bits and pieces, there seems to be no other way than tweaking them (without affecting the intended meaning) as I've done above.

Hi Alex,
Really great tutorial. However I am one of those people who is just revisiting c++ to brush up the skills and avoiding the pitfalls. I think what would be great is if you can add a small box (with an icon indicating danger) around text items where you give advice about dangers and common mistakes. That way it is easy for people like me to browse through this faster and for newbs to remember.

a lot of comments about the content of this lesson.
mine will be about the use of the term "program" for a snippet
and the usage of post(blah++) instead of pre(++blah) increment.
minor things but they confuse me as a beginner in what is the proper way.
i hope this comments are helpful for future updates and revisions instead of annoying 🙂

In the first block of code you reference, all your function names begin with a capital letter (e.g., DoAddition), but these should begin with a lowercase letter by naming conventions (e.g., doAddition)

When using break and/or continue in loops, try to have them either right at the start or end, preferably at the start, so they are easy to spot and thus keeping the control flow easy to read.

Another suggestion, wouldn't having a chapter about understanding the flow of the loops be appropriate? I'm mostly thinking of things like is there an invariant (eg. int count tells us which numbers has been printed so far) and are there any termination conditions, so the loop can actually terminate. And also as you touch upon with the continue are there any control flow that can make the termination condition(s) inaccessible.

Is there any elegant way to make this work as intended as a "while" function?
If you put the increment (iii++) before the if, then "0" never gets printed. The only way I know to get "0" included in the output this way is to initialize iii as -1, which seems like a very sloppy way to do things.
You could replace "continue;" with an "iii++" and get the desired result, , but I would like to see how this could be done, simply and elegantly, using the "continue" statement.