Почему изменение 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 ]

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

Они не ведут себя одинаково. Конструкция с i ++ немного медленнее, чем конструкция с ++ i , потому что первая включает в себя возврат как старых, так и новых значений i . С другой стороны, последний возвращает только старое значение i .

Тогда, возможно, компилятор немного творит и меняет любой изолированный i ++ на ++ i по соображениям производительности, но с точки зрения необработанного алгоритма они не строго совпадают .

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

В Stackoverflow много похожих постов:

Однако, кажется, ваш вопрос более общий, потому что он не относится ни к какому языку или компилятору. Большинство из приведенных выше вопросов касаются конкретного языка / компилятора.

Вот краткое изложение:

  • если мы говорим о C / C ++ / Java (возможно, также C #) и современном компиляторе:
    • , если i является целым числом (const int, int и т. Д.):
      • тогда компилятор в основном заменит i++ на ++i, потому что они семантически идентичны и поэтому не изменяют вывод. это можно проверить, проверив сгенерированный код / ​​байт-код (для Java я использую средство просмотра байт-кода jclasslib ).
    • еще:
  • еще:
    • все ставки отключены, потому что компилятор не может гарантировать, что они семантически идентичны, поэтому он не пытается оптимизировать.

Так что если у вас есть класс в C ++, который переопределяет постфиксные и префиксные операторы (например, std::iterator), эта оптимизация выполняется редко, если вообще когда-либо.

В итоге:

  • Имею в виду, что вы говорите, и говорите, что вы имеете в виду. Для инкрементной части циклов for вам почти всегда требуется версия префикса (т. Е. ++i).
  • Переключатель компилятора между ++i и i++ не всегда может быть выполнен, но он попытается сделать это за вас, если сможет.
0 голосов
/ 18 августа 2010

Вы правы. Разницу можно увидеть в этом случае:

for(int i = 0; i < 5; )
       {
            System.out.println("i is : " + ++i);           
       }
0 голосов
/ 09 октября 2010

в цикле, сначала инициализация, затем проверка состояния, затем выполнение, после этого увеличения / уменьшения. поэтому увеличение / уменьшение до / после не влияет на программный код.

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

Да, это происходит последовательно. Инициализация, затем условие оценки, и если true, то выполнение тела с последующим увеличением.

Разница префикса и постфикса будет заметна только тогда, когда вы выполняете операцию Назначения с Приращением / Уменьшением.

0 голосов
/ 13 апреля 2018

Между постом и оператором преинкремента существует большая путаница, это легко понять из выдержки из "Алгоритмы, 4-е издание Роберта Седжвика и Кевина Уэйна"

Операторы увеличения / уменьшения: i ++ совпадает с i = i + 1 и имеет значение я в выражении. Аналогично, i-- такой же, как i = i - 1. Код ++ i и --i одинаковы, за исключением того, что значение выражения берется после увеличения / декремент, не раньше.

например

x = 0; 
post increment:
x++;
step 1: 
assign the old value (0) value of the x back to x.So, here is x = 0.
step 2:
after assigning the old value of the x, increase the value of x by 1. So,
x = 1 now;

when try to print somthing like:
System.out.print(x++);
the result is x : 0. Because only step one is executed which is assigning 
old value of the x back and then print it.

But when, we do operation like this: 
i++;
System.out.print(i);
the result is x: 1. which is because of executing Step one at first 
statement and then step two at the second statement before printing  the 
value.

pre increment:
++x;
step 1: 
increase the value of x by 1. So, x = 1 now;
step 2:
assign the increased value back to x.

when try to print something like:
System.out.print(++1)  
the result is x : 1. Because the value of the x is raised by 1 and then 
printed. So, both steps are performed before print x value. Similarly, 
executing 
++i;
system.out.print(i);
Both steps are executed at statement one. At second statement, just the 
value of "i" is printed.
0 голосов
/ 17 декабря 2009

Потому что это:

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

Эффективно переводится компилятором в это:

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

Как видите, использование y-- или --y не приводит к разнице. Это имело бы значение, если бы вы написали свой цикл следующим образом:

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

Это дало бы тот же результат, что и два ваших варианта цикла, но изменение здесь с --y на y-- нарушило бы вашу программу.

...