Expressions and statements
ES.77
Минимизируйте использование `break` и `continue` в циклах
Причина
В нетривиальном теле цикла легко пропустить break или continue.
break в цикле имеет принципиально иное значение, чем break в операторе switch (а switch может находиться внутри цикла, и цикл — внутри ветки switch).
Пример
switch(x) {
case 1 :
while (/* некое условие */) {
// ...
break;
} // Упс! break выходит из switch или из while?
case 2 :
// ...
break;
}
Альтернатива
Зачастую цикл, требующий break, является хорошим кандидатом для выделения в функцию (алгоритм), где break заменяется на return.
// Исходный код: break внутри цикла
void use1()
{
std::vector<T> vec = {/* инициализирован некоторыми значениями */};
T value;
for (const T item : vec) {
if (/* некое условие*/) {
value = item;
break;
}
}
/* затем что-то делаем с value */
}
// ЛУЧШЕ: создать функцию и вернуть значение из цикла
T search(const std::vector<T> &vec)
{
for (const T &item : vec) {
if (/* некое условие*/) return item;
}
return T(); // значение по умолчанию
}
void use2()
{
std::vector<T> vec = {/* инициализирован некоторыми значениями */};
T value = search(vec);
/* затем что-то делаем с value */
}
Цикл с continue зачастую может быть эквивалентно и столь же ясно выражен через оператор if.
for (int item : vec) { // ПЛОХО
if (item%2 == 0) continue;
if (item == 5) continue;
if (item > 10) continue;
/* что-то делаем с item */
}
for (int item : vec) { // ХОРОШО
if (item%2 != 0 && item != 5 && item <= 10) {
/* что-то делаем с item */
}
}
Примечание
Если действительно нужно прервать цикл, break обычно лучше альтернатив, таких как изменение переменной цикла или goto.
Контроль
???