Recently, I've been looking at various C++ code examples where you have something like the following:
//líneas de código
for (i = 0; i < n; i++)
{
if((alguna_condición))
{
//más código
break;
}
}
//siguen más líneas de código
In my C++ classes I have only used the statement break
with the conditional structure switch
and so I was a bit surprised by the use of break
with the repetitive structure for
. Searching in Google I found the following links , however the only thing that I have achieved is to confuse me. From what I've read, for some break
there's nothing wrong with using, but for others it's just as bad as using the infamous goto
.
Basically my question, as the title suggests, is it okay to use break
in repetitive control structures, and if not, is it as "harmful" as using goto
?.
Thanks in advance for comments and/or responses.
It is perfectly valid; that's your mission, to get out of the current code block; more specifically, its use is limited to blocks:
switch
do
while
for
It is not valid to exit blocks
if
(that are not contained in any of the previous blocks):Nor for anonymous scopes (equally not contained in any of the valid blocks) :
It also does n't allow exiting nested blocks :
In that example,
break
exit the innermost block ; i.e. it only works for the block it is included in .Using
break
is just as bad as using any other C++ utility: nothing bad. The evil is not in the utility used but in the use that is given to it. As you have pointed out, it is often used to alter the natural flow of a loop, for example by iterating through a collection until a specific element is found:Ejemplo1
There is nothing wrong with the previous code: it goes through a collection of objects (
principes
) to which it performs a test (es_azul
) and at the end of the loop the variableindice
contains the index of the first object that meets said condition orprincipes.size()
if there is none; the above code is almost equivalent to this:Ejemplo2
There can be heated debates about which of the two versions is better, but in general, these discussions will not focus on the use of
break
but on number of instructions (the loopEjemplo2
takes one more turn) or clarity (Ejemplo1
it can be more difficult to understand). .Whatever the case, you will hardly see
Ejemplo1
itEjemplo2
in modern C++, since it is usual to delegate this type of operations to the header<algorithm>
:Each compiler will implement it
std::find_if
in<algorithm>
its own way but in general the implementation might look like:The instruction
return first;
inside the loop works in a similar way to thebreak
ones you put in your example: they alter the natural flow of the loop and as you can see it is used in standard library code, nothing to object to, right?I'm going to be the dissonant voice: although
break
(andcontinue
, another operation that often falls into the same bag asbreak
) is technically valid and can be used to break out of conditional/iterative structures, if it can be avoided, it shouldn't be used for that in programming high level (with some exceptions). Key part: " if it can be avoided ".It's not as bad (or should I say harmful ?) as
goto
because you know exactly where you're going to go when you do abreak
(at the end of the block that contains it), but with it you're breaking the normal flow of the structure which isn't either. is ideal, makes the code less readable (although this is debatable), and can lead to unexpected results.For example, if you are reviewing the following code and you get to the header of
for
, you would expect that when the loop ends, the value ofx
is greater than or equal to 100. Which is not going to happen because N lines below there is abreak
:The real problem comes because people do not use them well and abuse them. For example, in the case above where there is a
break
inside a loopfor
, what really happens is that the correct structure has not been selected:break
refactoring the code to a loopwhile
or a could be avoideddo...while
:Another problem with
break
, as Trauma indicates , arises if you have two nested iterative structures where only the inner one is to be exited, but what if we wanted to exit both? Shall we do a secondbreak
? Shall we check again? In that case, perhaps it would be better to use a sentinel variable, eg.In short: as long
break
as theycontinue
are technically valid (and in some cases even necessary) and can work perfectly well in clean and tidy code... but that is not always the case, and their use (or abuse) can lead to problems and bad practices.