This question is at risk of being a duplicate of Are `break` and `continue` bad programming practices? but I will try to give a more theoretical explanation.
I forgot the reference but I would appreciate if someone can find it and I will be happy to include it here, or you can edit into my answer without asking if you have the reps.
The theoretical explanation was originally given to support some limited use of goto, and the justification to these limited usage later gave rise to the structured control flow statements we're familiar today.
The justification is this. Perform the following exercise on paper:
- For the purpose of this exercise, treat all control transfers (both unconditional and conditional) as
goto
.
- List the program code for a single function. If you would like to analyze more than one function, inline it into the top-level function.
- Draw arrows to connect each
goto
to the branch target.
- Put all backward- (upward-) going branch arrows on the left of the program listing.
- Put all forward- (downward-) going branch arrows on the right of the program listing.
- If you can figure out a way to arrange those arrows without any two crisscross each other, your code is said to have a sensible control transfer structure.
(The terminology used here may have diverged from the original reference.)
Now let's examine the two keywords being questioned: break
and continue
.
I assume that your are referring to their use inside loops. As others point out, break
is mandatory in switch
statements (or at least your future employer's coding standards would have made that mandatory), so there is no point in arguing.
break
is simply a control transfer to the bottom (exit) of the loop. Therefore it does not crisscross the control flow of the loop itself.
continue
transfers to the top (loop advance and condition test) of the loop. If the condition test is false it also exits the loop. Note that the "if condition test fails ..." part is a different control flow. continue
only needs to transfer to the top.
Simply put, break
and continue
used inside a loop doesn't violate the sensible control flow structure. This is why they are allowed in the first place in historically significant languages such as Pascal, etc where language design trumps practical considerations.
Now, regarding some posts saying that break
is bad if it appears in the middle of some non-side-effect-free code - I would say yes and no.
Most of the time, if you see this happening, it is because it has to be so. The reality makes this argument moot.
Example: in some of your code, you have to do this inside a loop:
- Check condition A first. If it fails you can do
break
(or continue
, depending on the task).
- Only if condition A is satisfied, you can start computing some value B.
- With B computed, you will also check condition B (using the value of B).
Can you move the condition check B to the top of the loop? You can't. It's dictated by the nature of the task you are implementing. Thus the argument is moot. If at all, that argument favors decomposing long functions into shorter subroutines, rather than arguing for careful positioning of the use of break
statements.