Почему изменение pre на post увеличивается в итерационной части цикла for? - PullRequest
37 голосов
/ 17 декабря 2009

Почему это

 int x = 2;
    for (int y =2; y>0;y--){
        System.out.println(x + " "+ y + " ");
        x++;
    }

печатает так же, как этот?

 int x = 2;
        for (int y =2; y>0;--y){
            System.out.println(x + " "+ y + " ");
            x++;
        }

Насколько я понимаю, постинкремент сначала используется "как есть", а затем увеличивается. Предварительно инкремент сначала добавляется, а затем используется. Почему это не относится к телу цикла for?

Ответы [ 27 ]

58 голосов
/ 17 декабря 2009

Цикл эквивалентен:

int x = 2;
{
   int y = 2;
   while (y > 0)
   {
      System.out.println(x + " "+ y + " ");
      x++;
      y--; // or --y;
   }
}

Как видно из чтения этого кода, не имеет значения, используете ли вы оператор post или pre-decment в третьем разделе цикла for.

В общем, любой for цикл формы:

for (ForInit ; Expression ; ForUpdate)
    forLoopBody();

в точности соответствует циклу while:

{
    ForInit;
    while (Expression) {
        forLoopBody();
        ForUpdate;
    }
}

Цикл for более компактен, и, следовательно, его легче разобрать для такой распространенной идиомы.

27 голосов
/ 18 августа 2010

Чтобы визуализировать эти вещи, разверните цикл for до цикла while:

for (int i = 0; i < 5; ++i) {
    do_stuff(i);
}

Расширяется до:

int i = 0;
while (i < 5) {
    do_stuff(i);
    ++i;
}

Неважно, будете ли вы выполнять постинкрементное или предварительное увеличение счетчика цикла, потому что результат выражения приращения (значение до или после приращения) не используется внутри одного и того же оператора.

17 голосов
/ 12 апреля 2010

Нет разницы с точки зрения производительности, если это ваша забота. Он может использоваться неправильно (и, следовательно, чувствителен к ошибкам), когда вы используете это во время приращения.

Рассмотрим:

for (int i = 0; i < 3;)
   System.out.print(++i + ".."); //prints 1..2..3


for (int i = 0; i < 3;)
   System.out.print(i++ + ".."); //prints 0..1..2

или

for (int i = 0; i++ < 3;)
   System.out.print(i + ".."); //prints 1..2..3


for (int i = 0; ++i < 3;)
   System.out.print(i + ".."); //prints 1..2

Интересно, однако, что обычная идиома заключается в использовании i++ в выражении приращения оператора for и что компилятор Java скомпилирует его, как если бы использовался ++i.

13 голосов
/ 18 августа 2010

++ i и i ++ имеют значение при использовании в сочетании с оператором присваивания, таким как int num = i ++ и int num = ++ i или другими выражениями. В вышеприведенном цикле FOR есть только условие приращения, так как оно не используется в сочетании с любым другим выражением, оно не имеет никакого значения. В этом случае это будет означать только i = i + 1.

6 голосов
/ 18 августа 2010

Этот цикл такой же, как этот while цикл:

int i = 0;
while(i < 5)
{
     // LOOP
     i++; // Or ++i
}

Так что да, это должно быть то же самое.

5 голосов
/ 17 декабря 2009

Потому что это утверждение само по себе. Порядок приращения там не имеет значения.

4 голосов
/ 12 апреля 2010

Эти два случая эквивалентны, потому что значение i сравнивается после выполнения инструкции приращения. Тем не менее, если вы сделали

if (i++ < 3) 

против

if (++i < 3)

тебе придется беспокоиться о порядке вещей.

А если ты сделал

i = ++i + i++;

тогда ты просто чокнутый.

3 голосов
/ 19 августа 2010

Вывод такой же, потому что элемент 'increment' в 'for (начальный; сравнение; приращение)' не использует результат оператора, он просто полагается на побочный эффект оператора, который в данном случае увеличивает 'i', что одинаково в обоих случаях.

3 голосов
/ 17 декабря 2009

Поскольку в ваших примерах ничего не является с использованием значения, возвращаемого до или после увеличения. Попробуйте обернуть System.out.println() вокруг ++x и x++, чтобы увидеть разницу.

3 голосов
/ 17 декабря 2009

Из главы Спецификация языка Java для циклов :

BasicForStatement:

    for ( ForInit ; Expression ; ForUpdate ) Statement

... если присутствует часть ForUpdate, выражения оцениваются в последовательность слева направо; их значения, если они есть, отбрасываются. ... Если часть ForUpdate отсутствует, никаких действий не предпринимается.

(выделение мое).

...