кроме того, то, когда Ваши классы являются крошечными и обычно окончательными, будучи защитными, действительно дешево - мог бы также добавить его независимо от того, если Вы верите в него или нет. Протестируйте значения, передаваемые Вашим конструкторам и (если у Вас действительно ДОЛЖНЫ быть они), методы set.
Насколько я знаю, нет веской причины. Вы намеренно вводите людей в заблуждение, используя цикл for, который ничего не увеличивает.
Обновление:
Основываясь на комментарии OP к вопросу, я могу предположить, как вы можете увидеть такую конструкцию в реальном коде. . Я видел (и использовал) это раньше:
lots::of::namespaces::container::iterator iter = foo.begin();
for (; iter != foo.end(); ++iter)
{
// do stuff
}
Но это все, что я могу сказать о том, чтобы оставить вещи вне цикла for. Возможно, в вашем проекте был цикл, который когда-то выглядел так. Если вы добавляете код, удаляющий элементы контейнера в середине цикла, вам, вероятно, придется тщательно контролировать, как увеличивается iter
. Это может привести к тому, что код будет выглядеть следующим образом:
for (; iter != foo.end(); )
{
// do stuff
if (condition)
{
iter = foo.erase(iter);
}
else
{
++iter;
}
}
Однако это не оправдание, если вы не потратили пять секунд, чтобы преобразовать его в цикл while.
Раньше я писал довольно загадочный код на C / C ++. Оглядываясь назад, я, вероятно, сделал бы это в цикле while:
ifstream f("file.txt");
char c;
for(f.get(c); !f.eof(); f.get(c)) {
// ...
}
Я полагаю, что моя точка зрения состоит в том, что циклы for обычно короче, но менее читабельны, если они не используются в традиционном смысле цикла по диапазону.
Возможно, вы захотите использовать цикл do-while вместо цикла for, чтобы код обрабатывался хотя бы один раз, прежде чем условия будут проверены и выполнены (или нет ).
На этот вопрос был дан ответ - язык имеет более естественную конструкцию для выражения того, что вы хотите - вы должны ее использовать. Например, я, конечно, могу написать это:
for (bool b = condition(); b; b = !b) {
/* more code */
}
или:
while (condition()) {
/* more code */
break;
}
вместо более обычного:
if (condition()) {
/* more code */
}
Но почему? C (и все языки) имеют идиомы, и большинство из них имеют рациональный смысл с точки зрения выразительности и ожидания значения. Когда вы играете с идиомой, вы мешаете чувствам человека, который должен читать ваш код.
В языках Си действительно нет разницы между циклом for (; cond;) и циклом while. Обычно то, что я делаю на языках Си, - это начинаю писать цикл как «for» и меняю его на «while», если я получаю эту форму. Это довольно редко, так как вы всегда повторяете что-то , а C позволяет вам поместить любой код, который вы хотите, в эту последнюю область.
Было бы иначе, если бы C имел real (предварительно вычисленная итерация) для циклов.
Я вижу 2 причины, ни одну из которых я бы не рассмотрел:
Если оставить в стороне удобство чтения на некоторое время, обычно нет разницы в производительности между разными циклами. По крайней мере, нет существенной разницы.
Для настольных приложений вы можете выбрать на основе критериев удобочитаемости. Обратитесь к другим сообщениям - например, глядя на цикл for, кто-то думает, что инкрементор объявлен внутри цикла.
Кажется, для веб-приложений, например, сценариев на стороне клиента, может быть разница.
Посетите этот сайт: http://www.websiteoptimization.com/speed/10/10-2.html
Проведите собственные эксперименты и руководствуйтесь результатами, иначе придерживайтесь правил удобочитаемости.
Я думаю, что имеются в виду циклы «while» и «for» для разных идиом. Идиома использования «while» - «делать что-то, пока выполняются определенные условия». Идиома для "for" - "перебирать определенный диапазон элементов" ...
Когда я читаю код, я ожидаю этих идиом (и я думаю, что не одинок). Когда я вижу "for", я понимаю, что кто-то выполняет итерацию в определенном диапазоне, и я не вдавался в подробности. Когда я вижу цикл for, используемый для другой идиомы (не той, как я ожидаю), я сбиваюсь с толку и вынужден вдаваться в подробности.
Во всяком случае, это очень субъективно ...
, если вы хотите сделать что-то ограниченное количество раз, тогда "for" позволяет вам указать ограничение, не смешивая его с логикой внутри вашего цикла.
В этом случае я лично предпочитаю первый цикл, так как его легче писать и читать.
Но если у меня есть цикл, которому нужен какой-то оператор post, я бы использовал цикл for следующим образом:
for (; i < 10; i += 2)
На уровне сборки могут быть небольшие различия, зависящие от компилятора, но в идеале оба должны вести себя точно так же, а первый более читабелен. Так что нет никаких оснований использовать последнюю версию, кроме нонконформизма.
Можно скомпилировать
for(INIT; CONDITION; UPDATE)
{
BODY
}
в
{
INIT
while(CONDITION)
{
BODY
UPDATE
}
}
ОБНОВЛЕНИЕ: кажущаяся избыточной дополнительная область видимости заключается в том, чтобы поместить любые определения переменных в INIT, то есть из для (int i = 0;. ..)
. Спасибо!
По сути, это просто перестановка выражений. Так что нет причин отдавать предпочтение одному другому по соображениям производительности. Я бы порекомендовал while ()
, если это возможно, поскольку это проще. Если более простая конструкция выражает то, что вы хотите сделать, я думаю, что использовать ее.
Нет. Нет. Нет.
Даже если бы была микроскопическая разница в производительности, вам пришлось бы быть джедаем-тюнером на конечном этапе, чтобы это было достаточно важно, чтобы заботиться.
Скомпилируйте оба и проверьте полученный дизассемблер, если они одинаковы (что, вероятно, так и есть).
Некоторые компиляторы предупреждают об условиях постоянного цикла:
while (true) { /* ... */ } /* Warning! */
for (;;) { /* ... */ } /* No warning */
По этой причине в конкретном случае бесконечного цикла я мог бы выбрать цикл for вместо цикла while. Но если условие не пустое, пользы особо не вижу. Я предполагаю, почему он появился в упомянутом проекте, потому что код каким-то образом эволюционировал в процессе обслуживания, но изначально был написан более традиционным способом.
Есть ли причина использовать последнее вместо первого?
Насколько мне известно, эти два оператора в любом случае оптимизируются компилятором в один и тот же ассемблерный код ... так что нет, нет причин для этого - только личные предпочтения.