Скажем, у вас есть следующий for
цикл *:
for (int i = 0; i < 10; ++i) {
// ...
}
который обычно можно записать так:
for (int i = 0; i != 10; ++i) {
// ...
}
Конечные результаты одинаковы, так есть ли реальные аргументы для использования одного над другим? Лично я использую первое в случае, если i
по какой-то причине выходит из строя и пропускает значение 10.
* Извините за использование магических чисел, но это всего лишь пример.
int i = 10; while(i --> 0) { /* stuff */ }
while ((i--) > 0)
Ответы:
Причина выбора одного или другого из-за намерения, и в результате этого, это увеличивает удобочитаемость .
Намерение: цикл должен выполняться до тех пор, пока
i
он меньше 10, а не до тех пор, покаi
он не равен 10. Несмотря на то, что последний может быть одинаковым в данном конкретном случае, это не то, что вы имеете в виду, поэтому он не должен быть написано такЧитаемость: в результате записи вы понимаете, что это также легче понять. Например, если вы используете
i != 10
, кто-то, читающий код, может задаться вопросом, может ли внутри цикла каким-то образомi
стать больше 10, и что цикл должен продолжаться (кстати: это плохой стиль, чтобы связываться с итератором где-то еще, чем в головеfor
-statement, но это не означает , что люди не делают этого , и в результате сопровождающие ожидают его).источник
i
он «меньше 10», он должен выполняться до тех пор, пока (в этом случае) верхняя граница не достигнута. При использовании C ++ интервал / итератора диапазон обоснование, это гораздо более логично , чтобы выразить это через!=
чем<
.<
это точно выражается.for
цикла. Использовать<
здесь было бы глупо. Кроме того, Deckard, кажется, признает это. Я очень согласен с его комментарием в ответ на мой.!=
<
Картина , как правило , работает даже если приращение происходит не быть 1 точно.Это позволяет использовать один общий способ выполнения циклов независимо от того, как это делается на самом деле.
источник
i
совершенно безопасно модифицировать внутри цикла.<
, такие как итераторы над последовательностью, и поэтому!=
это будет единственный распространенный способ создания циклов в C ++.<
шаблону, потому что он требует одного нажатия клавиши вместо двух с>
шаблоном и четырех с!=
. Это вопрос эффективности, подобной ОКР.В C ++ рекомендация Скотта Майерса в «Более эффективном C ++» (пункт 6) всегда заключается в использовании второго, если только у вас нет для этого причин, потому что это означает, что у вас одинаковый синтаксис для итерационных и целочисленных индексов, поэтому вы можете легко переключаться между
int
итератором без каких-либо изменений в синтаксисе.На других языках это не применимо, так что я думаю, что
<
это, вероятно, предпочтительнее из-за мнения Торбьерна Равна Андерсена.Кстати, на днях я обсуждал это с другим разработчиком , и он сказал , что причина предпочесть
<
более!=
потому , чтоi
может случайно увеличивается на более чем один, и это может вызвать состояние перерыв не должны быть выполнены; это ИМО груз чепухи.источник
<
более безопасным программирование, чем!=
тогда ...<
является более оборонительным, и мои коллеги ненавидят это, если я пишу,!=
поэтому я не Тем не менее, есть случай для!=
C ++, и это то, что я представил.i++
- это изменение цикла while в цикл for. Не уверен, что иметь половину числа итераций лучше, чем (почти) бесконечный цикл; последнее, вероятно, сделает ошибку более очевидной.Использование (я <10), на мой взгляд, более безопасная практика. Он улавливает максимальное количество возможных случаев выхода из программы - все, что больше или равно 10. Сравните это с другим случаем (i! = 10); это ловит только один возможный случай отказа - когда мне ровно 10.
Побочным продуктом этого является то, что он улучшает читабельность. Кроме того, если приращение будет чем-то другим 1, это может помочь минимизировать вероятность проблемы, если мы допустим ошибку при написании прекратить работу.
Рассмотреть возможность:
Хотя оба случая, скорее всего, ошибочны / неправильны, второй, скорее всего, будет БОЛЬШЕ неправильным, поскольку он не выйдет. Первый случай завершится, и существует более высокая вероятность того, что он выйдет в нужном месте, даже если 14, вероятно, неправильное число (15, вероятно, будет лучше).
источник
Вот еще один ответ, который, кажется, еще никто не придумал.
for
Циклы следует использовать, когда вам нужно перебрать последовательность . Использование!=
является наиболее кратким методом определения условия завершения цикла. Однако использование менее строгого оператора является очень распространенной идиомой защитного программирования. Для целых чисел это не имеет значения - это просто личный выбор без более конкретного примера. Цикл по коллекциям с итераторами, которые вы хотите использовать!=
по причинам, указанным другими. Если вы считаете последовательностиfloat
илиdouble
, то вы хотите избежать!=
любой ценой.Я хотел бы отметить, что
for
он используется, когда вам нужно перебрать последовательность. Сгенерированная последовательность имеет начальную точку, интервал и условие завершения. Они кратко указаны вfor
заявлении. Если вы обнаружите, что либо (1) не включает шаговую частьfor
или (2), указав что-то вродеtrue
условия охраны, то вам не следует использоватьfor
цикл!while
Цикл используются для продолжения обработки в то время как состояние конкретного удовлетворяются. Если вы не обрабатываете последовательность, то, скорее всего, вам нуженwhile
цикл. Аргументы охранного условия здесь аналогичны, но решение между awhile
иfor
циклом должно быть очень осознанным.while
Цикл недооцениваемый в кругах C ++ ИМА.Если вы обрабатываете коллекцию элементов (очень распространенное
for
использование -loop), то вам действительно следует использовать более специализированный метод. К сожалению,std::for_each
это довольно болезненно в C ++ по ряду причин. Во многих случаях отделение телаfor
петли в отдельно стоящей функции (хотя и несколько болезненно) приводит к гораздо более чистому решению. При работе с коллекциями, рассмотримstd::for_each
,std::transform
илиstd::accumulate
. Реализация многих алгоритмов становится лаконичной и кристально ясной, когда выражается таким образом. Не говоря уже о том, что выделение тела цикла в отдельную функцию / метод заставляет вас сосредоточиться на алгоритме, его входных требованиях и результатах.Если вы используете Java, Python, Ruby или даже C ++ 0x , вы должны использовать правильный цикл foreach для коллекции . По мере того как компиляторы C ++ реализуют эту функцию, ряд
for
циклов исчезнет, как и обсуждения этого типа.источник
while
,for
иforeach
(или языковой эквивалент)while
<
), или оператор, снисходительный в значениях, которые он терпит неудачу (!=
).Использование «меньше чем» является (обычно) семантически правильным, вы действительно имеете в виду считать до тех пор,
i
пока не станет больше 10, поэтому «меньше чем» ясно передает ваши намерения. Использование «не равно», очевидно, работает практически в случаях вызова, но передает немного другое значение. В некоторых случаях это может быть то, что вам нужно, но по моему опыту, это никогда не было так. Если у вас действительно был случай, когдаi
может быть больше или меньше 10, но вы хотите продолжать цикл до тех пор, пока он не станет равным 10, тогда этот код действительно нуждается в очень четком комментировании, и, возможно, его лучше написать с помощью другой конструкции, какwhile
петля возможно.источник
Одна из причин , почему я выступает за
less than
большеnot equals
, чтобы действовать в качестве охранника. В некоторых ограниченных обстоятельствах (плохое программирование или дезинфекция) ониnot equals
могут быть пропущены, тогда какless than
они все еще будут действовать.Вот один пример, когда отсутствие проверки очистки привело к странным результатам: http://www.michaeleisen.org/blog/?p=358
источник
Вот одна из причин, почему вы предпочитаете использовать,
<
а не!=
. Если вы используете язык с глобальной областью видимости переменных, что произойдет, если другой код изменитсяi
? Если вы используете<
вместо!=
, то худшее, что происходит, - это то, что итерация заканчивается быстрее: возможно, какой-то другой код увеличиваетсяi
случайно, и вы пропускаете несколько итераций в цикле for. Но что произойдет, если вы выполняете цикл от 0 до 10, и цикл становится равным 9, и по какой-i
то странной причине некоторые плохо записанные потоки увеличиваются . Затем ваш цикл завершает эту итерацию и увеличивает ееi
до значения 11. Теперь, когда цикл пропустил условие выхода (i
никогда не равное 10), он теперь будет выполняться бесконечно.Это не обязательно должно быть особенно причудливой логикой типа threading-and-global-variable, которая вызывает это. Возможно, вы просто пишете цикл, который необходимо откатить назад. Если вы мутируете
i
в цикле и запутываете свою логику, то, имея ее так, чтобы она имела верхнюю границу, а не a,!=
вы вряд ли оставите вас в бесконечном цикле.источник
Во встроенном мире, особенно в шумной среде, вы не можете рассчитывать на то, что ОЗУ будет вести себя должным образом. В условном (для, в то время как, если), где вы сравниваете, используя '==' или '! =', Вы всегда рискуете, что ваши переменные пропустили это критическое значение, которое завершает цикл - это может иметь катастрофические последствия - Mars Lander уровень последствий. Использование «<» или «>» в условии обеспечивает дополнительный уровень безопасности для обнаружения «неизвестных неизвестных».
В исходном примере, если бы по
i
необъяснимым причинам катапультировалось до значения, намного превышающего 10, сравнение «<» сразу же уловит ошибку и выйдет из цикла, но «! =» Продолжит считать, пока неi
обернется вокруг 0 и обратно. до 10.источник
for (i=4; i<length; i++) csum+=dat[i];
где допустимые пакеты всегда будут иметьlength
по меньшей мере четыре, но один может получить поврежденные пакеты. Если разные типы пакетов имеют разные требования к длине, может потребоваться проверить длину как часть обработки, которая отличается для каждого типа пакета, но сначала проверьте контрольную сумму как часть общей логики. Если получен пакет недостаточной длины, на самом деле не имеет значения, сообщает ли вычисление контрольной суммы «хорошо» или «плохо», но это не должно привести к сбою.