Using goto , using continue , using multiple break or using multiple return are all if they are abused, different spaghetti coding options, all of which can be used to create non-conditional branches. Some examples of abuse:
goto is considered very bad if it is used for anything other than a jump down, for example, for an error handler. (While this may be an acceptable use of goto , it still starts all the debate related to the loss of a dead horse - the so-called harmful debate, so I would avoid goto only for this reason.)
continue non-specifically jumps up, which is considered bad: one definition of spaghetti code is a code that jumps unconditionally, either up or down. This is especially bad when a few continue added to the same loop. In general, the existence of continue is a fairly definite sign of a loop that needs to be rewritten.
Multiple break and multiple return can be abused to break out of complex, nested loops, which makes the code difficult to read and maintain. In addition, the break method, as shown in the question, provides the use of a somewhat obscure do-while (false) loop.
Typically, all of these methods are considered bad practice because they can be easily abused. You just need to choose the one that is the least bad: in other words, the most read and least obscure.
I believe that multiple returns are the most readable form, since it can be mixed with some function result variable, which you might want to have anyway:
result_t func () { if (a) { doA(); return RESULT_A; } ...
A note on the allocation of resources within a function.
If the above function should free some allocated resources, and it should always do this, you should do it with RAII, so that when a local variable goes out of scope, it cleans itself.
If in some cases it is required to free some allocated resources (for example, if an error occurs), you should not do this inside each if statement (invalid), and you should not implement the 1980s BASIC programmer "by mistake goto". Instead, consider adding a wrapper function outside the main function so that the program is maintained and minimizes clutter:
result_t wrapper () { stuff = allocate(); // if needed result_t result = func(stuff); if(result == BAD) { deallocate(stuff); } return result; }
source share