Бесконечные циклы - это плохие новости, только если они не предназначены или их использование имеет непреднамеренные последствия. Если вы используете их с намерением, нет никакой разницы с любой другой классификацией цикла, которую вы могли бы рассмотреть. Однако вы все равно будете ломать вещи, несмотря на намеренное использование. Обычно эта форма используется, когда вы хотите получить доступ к итератору или компоненту индекса после завершения цикла, например:
index = 0;
result = null;
for (;;)
result = foo(index);
if (bar(result))
break;
index += result;
use(index, result);
Обратите внимание, что изменение данных за пределами области действия цикла может быть очень нежелательным в зависимости от контекста, поэтому, действительно ли это хороший вариант использования, действительно зависит от контекста. Для другого подобного примера фактический итератор может быть объектом, желаемым вне цикла, но его инициализация в заголовке цикла не позволит получить доступ за пределами цикла. Бесконечный цикл решил бы эту проблему.
for (foo.iterator(); foo.hasNext(); ) {
use(foo.next());
}
keep_using(foo.next()); // throws an error
Кроме того, бесконечные циклы могут в некоторых случаях улучшить читаемость, особенно если есть много условий прерывания, но они могут не все происходить из взаимоисключающих единиц. Например, представьте, что у нас есть следующее:
for (;;) {
if (condition1)
break;
else if (condition2)
do_stuff();
else if (condition3)
break;
else
do_something();
}
Это можно переписать, используя три компонента цикла:
for (condition = true; condition; iteration) {
if (condition1 || condition3)
condition = false;
else if (condition2)
do_stuff();
else
do_something();
}
Однако, если мы внесем небольшое количество изменений (по крайней мере, с точки зрения символов на экране) в исходный код:
for (;;) {
if (condition1);
break;
if (condition2);
do_stuff();
if (condition3);
break;
else
do_something();
}
Переписывание становится тем, что требует от нас поиска этой дополнительной переменной:
for (condition = true; condition; iteration) {
if (condition1)
condition = false;
if (condition2) {
do_stuff();
condition = true;
}
if (condition3)
condition = false;
else {
do_something();
condition = true;
}
}
Это может быстро стать трудным для чтения и обслуживания по мере того, как тело цикла, и особенно возрастает сложность, например, если в condition
действительно было много различных условий, таких как a || b || c < d || (e > f) && (a > f)
; или, цикл содержал несколько вложенных циклов. Хотя вы можете применить ту же логику к другой оригинальной измененной версии.
Еще один пример, связанный с читабельностью, включает в себя подробную инициализацию, хотя, по общему признанию, это не очень хороший вариант использования:
for (more_long = some_ridiculously_long.initialization_statement.longer_than.Long_Long_Mans_Sakeru_gummy();
more_long < lots_of && more_long < break_conditions
maybe_even_an_update_that_hangs_at_ninety_nine_percent) {
...
}