Ты отличаешься между x ++ и ++ x

В коде я вижу часто x++ в циклах, но когда-нибудь я нахожусь ++x.

Есть какое-то различие между этими двумя выражениями?

47
задан 06.09.2017, 11:13
7 ответов

В коде я вижу часто x++ в loops, но когда-нибудь нахожусь ++x.

, Если ты имеешь в виду конструкции этого типа:

public static void main(String[] args) {
    for (int i = 0; i < 10; ++i) {
        System.out.println(i);
    }
    for (int i = 0; i < 10; i++) {
        System.out.println(i);
    }
}

... тогда не есть различие. Если мы видим bytecode :

public static void main(java.lang.String[]);
  Code:
     0: iconst_0
     1: istore_1
     2: iload_1
     3: bipush        10
     5: if_icmpge     21
     8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    11: iload_1
    12: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
    15: iinc          1, 1
    18: goto          2
    21: iconst_0
    22: istore_1
    23: iload_1
    24: bipush        10
    26: if_icmpge     42
    29: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    32: iload_1
    33: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
    36: iinc          1, 1
    39: goto          23
    42: return

В обоих случаях, справедливый человек despuГ©s призывания println (invokevirtual #3), увеличивает переменную 1 (в cГіdigo i для обоих случаев) в 1. VГ©ase iinc 1, 1 перед goto.


Тем не менее, если ты имеешь в виду что-то как это:

public static void main(String[] args) {
    for (int i = 0; i < 10;) {
        System.out.println(i++);
    }
    for (int i = 0; i < 10;) {
        System.out.println(++i);
    }
}

... тогда sГ - есть различие. Проверяя bytecode :

public static void main(java.lang.String[]);
  Code:
     0: iconst_0
     1: istore_1
     2: iload_1
     3: bipush        10
     5: if_icmpge     21
     8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    11: iload_1
    12: iinc          1, 1
    15: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
    18: goto          2
    21: iconst_0
    22: istore_1
    23: iload_1
    24: bipush        10
    26: if_icmpge     42
    29: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
    32: iinc          1, 1
    35: iload_1
    36: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
    39: goto          23
    42: return

В первом случае, сначала загружает стоимость переменной 1 (i), чтобы быть использованным в println. VГ©ase iload_1. DespuГ©s увеличивается эта переменная в 1. VГ©ase iinc 1, 1.

Во втором случае, сначала увеличивает стоимость переменной 1 (i) в 1, VГ©ase iinc 1, 1. Потом загружает стоимость переменной 1 (i), чтобы быть использованным в println. VГ©ase iload_1.

36
ответ дан 01.12.2019, 08:17

POST УВЕЛИЧИЛ:

x++, Стоимость выражения - стоимость переменной, нежели новая стоимость хранилась.

Пример:

int x = 1;
System.out.println(x++); // imprime 1.
System.out.println(x);   // imprime 2.

PRE УВЕЛИЧИЛ:

++x, Стоимость выражения - стоимость переменной после, что новая стоимость хранится.

Пример:

int x = 1;
System.out.println(++x); // imprime 2. 
System.out.println(x);   // imprime 2.

Сходный для x-- и --x

Примеры:

int x = 1;
System.out.println(x--); // imprime 1. 
System.out.println(x);   // imprime 0.

int x = 1;
System.out.println(--x); // imprime 0. 
System.out.println(x);   // imprime 0.

Больше информации:

37
ответ дан 01.12.2019, 08:17

Различие не, в котором увеличение работало раньше, или оценив выражение а в стоимости возврата двух выражений

Согласно официальной спецификации Java в секции: 15.14.2. Postfix Инкремент Оператор ++ и 15.15.1. Prefix Инкремент Оператор ++

15.14.2. Postfix Инкремент Оператор ++

... The оцените of the postfix increment expression is the оцените of the переменную before the new оцените is stored.

Перевод

15.14.2. Оператор Постустановленного Увеличения ++

Стоимость выражения постустановленного увеличения - стоимость переменной, нежели новая стоимость хранилась.

Также

15.15.1. Prefix Инкремент Оператор ++

The оцените of the prefix increment expression is the оцените of the переменную after the new оцените is stored.

Перевод

15.15.1. Оператор Увеличения Предопределил ++

Стоимость выражения увеличения префикса - стоимость переменной после, что новая стоимость хранится.

Оба увеличивают переменную x в 1. Различие - что выражение ++x возвращает стоимость увеличенной переменной взамен выражение x++ возврати первоначальную стоимость переменной перед тем, как быть увеличенной.

А именно:

int x = 5;
System.out.println(++x);  // Imprime 6, x vale 6: El resultado de la expresión ++x es 6 y se imprime 6
System.out.println(x); // Imprime 6, x vale 6: x ya se incrementó por lo que devuelve 6

В то время как:

int x = 5;
System.out.println(x++);  // Imprime 5, x vale 6. La variable x ya es 6 pero el resultado de la expresión es 5 por lo que se imprime 5
System.out.println(x); // Imprime 6, x vale 6: x ya se incrementó por lo que devuelve 6
17
ответ дан 01.12.2019, 08:17
  • 1
    Правильно то, что ты говоришь @CarlosMu и # 241; oz, уже revis и # 233; с linqpad, я думаю, что он немного смущен, когда ты говоришь " а в стоимости возврата две expresiones" так как est и # 225; возвращая ту же переменную, но во время отличные, в следующий p и # 225; rrafo ты это осветляешь, брать и # 233; время, чтобы отвечать вопрос в SO в ingl и # 233; s, я верю в то, что tambi и # 233; n он v и # 225; lido не?. – Juan Ruiz de Castilla 04.12.2015, 00:36
  • 2
    Этот спрашивает, что он относительно java, у LINQPad нет веса aqu и # 237; но должны быть другие decompiladores paa видеть bytecode – Carlos Muñoz 04.12.2015, 01:31
  • 3
    " Различие не est и # 225; в котором увеличение работало раньше или despu и # 233; s оценивания expresi и # 243; n а в стоимости возврата две expresiones" оба объяснения значат то же самое . Вторая, в самом деле, - следствие первой. – Darkhogg 04.12.2015, 09:52
  • 4
    +1. Действительно, схвати и # 237; он. Различие est и # 225; в стоимости, в которую eval и # 250; в expresi и # 243; n ++ x или x ++, как они показывают разделы 15.14.2 и 15.15.2 Java Лангвахе Спесификатион. – Jose Antonio Reinstate Monica 04.12.2015, 23:01
  • 5
    @Darkhogg, увеличение не работает ни раньше ни despu и # 233; s оценивания expresi и # 243; n а в течение evaluaci и # 243; n expresi и # 243; n а именно это часть c и # 243; я говорю произведенный составителем. У него нет l и # 243; gica думать, что выполняют сначала System.out.println() и потом eval и # 250; и expresi и # 243; n, что является Вашим аргументом, когда в действительности eval и # 250; сначала x++ и потом Ваш результат перемещен System.out.println(), оба префикс и я постзакрепляю они увеличивают переменную как результат оценивания expresi и # 243; n – Carlos Muñoz 05.12.2015, 01:51

Я знаю, что вопрос находится taggeada в Java, и не знаю осуществление в этом языке (хотя я предполагаю, что он будет сходным), но в C#, хотя нормальное и интуитивное а именно, что "один возвращает стоимость перед тем, как увеличивать, и другой после", и это более или менее дает основное значение... реальность состоит в том, что осуществление не является таким, и у него есть очень конкретная последовательность событий.

Это не проблема, если мы это используем только: x++; он не приносит никакой проблемы и простое объяснение действительное..., но если мы проникаем в мультитрэды, и длинные операции с различным предшествованием операторов, вещь меняется.

Как я говорю, не знаю, как это делает Java, но в C#, последовательность каждой команды верно определена (и я представляю, что в Java он будет сходным):

Для типа префикса (++x), последовательность:

  1. Он оценивается x чтобы производить переменную
  2. Стоимость переменной копируется во временное место
  3. Временная переменная увеличивается и производит новую стоимость (что не sobreescribe в ненастье)
  4. Новая стоимость сохраняет в переменной
  5. Он возвращает себе новую стоимость (не переменная)

Для типа суффикс (x++), последовательность:

  1. Он оценивается x чтобы производить переменную
  2. Стоимость переменной копируется во временное место
  3. Временная переменная увеличивается и производит новую стоимость (что не sobreescribe в ненастье)
  4. Новая стоимость сохраняет в переменной
  5. Он возвращает себе стоимость временной копии

Следовательно, последовательность событий происходит в обоих случаях в том же порядке, и не меняет даже оценки ни увеличение переменной, единственного, которую он меняет, - стоимость, которая возвращается. Только есть различие в шаге 5.

В C# используя расширение методов, это очень легкое для того, чтобы быть протестированным... в Java мне это не таково ясно (только у меня есть основные понятия Java).

Прощение из-за того, что я ответил используя C#, будучи taggeada вопрос как Java, но как уже я говорю, подозреваю, что осуществление должно быть сходным, если не равный.

4
ответ дан 01.12.2019, 08:17

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

  • ++ x это делает до того, как была оценена она expresiГіn. Также называются PREINCREMENTO

    Пример:

    int x = 5;
    System.out.println(++x); // escribira 6 porque ejecutará x + 1 ANTES de printar
    System.out.println(x);   // volverá a escribir 6!!!!
    
  • x ++ это делает позже в тот, что expresiГіn она была оценена. TambiГ©n называются POSTINCREMENTO

    Пример:

    int x = 5;
    System.out.println(x++); // escribirá 5 porque ejecutará x + 1 DESPUÉS de printar
    System.out.println(x);   // escribirá 6
    

Восток тип выражений также очень обычный, сделав ассигнования array, когда ты реализуешь цикл без счетчика (например for-each) или наполняя несколько свойств того же объекта избавляя так от линии кода и зарабатывая читабельность.

arrayALlenar[i++] = elemento;  

вместо

arrayALlenar[i] = elemento;  
i++;
2
ответ дан 01.12.2019, 08:17
  • 1
    System.out.println(x++); // escribirá 5 porque ejecutará x + 1 DESPUÉS de printar ., Хотя печатать и # 225; 5, explicaci и # 243; n она неправильная. Сначала eval и # 250; в аргумент x++ и потом работает м и # 233; совсем println. То, за чем оно действительно последует, состоит в том, что переменная увеличивается, но , оказанный из expresi и # 243; n быть и # 225; стоимость, которую имей, и # 237; в оригинально а следовательно он возвращает 5 – Carlos Muñoz 03.12.2015, 19:12
  • 2
    - 1. " ++ x" не " он это делает до того, как был оценен expresi и # 243; n. и quot; x eval и # 250; чтобы перед быть увеличенным. V и # 233; поджарьте раздел 15.15.2. Prefix Декремент Оператор - Java Лангвахе Спесификатион. – Jose Antonio Reinstate Monica 04.12.2015, 22:59
  • 3
    Correcci и # 243; n, я хочу сказать раздел 15.15.1. Prefix Инкремент Оператор ++ – Jose Antonio Reinstate Monica 04.12.2015, 23:22

++x увеличивает переменную перед тем, как быть вызовом. X++ пламя и despuГ©s он увеличивает ее.

2
ответ дан 01.12.2019, 08:17

Оба делают то же самое кроме того, что тот постувеличения оценивается в стоимость переменной ДО ТОГО, КАК хранилась увеличенная стоимость и стоимость предувеличения он оценивается в стоимость переменной ПОСЛЕ ТОГО, КАК хранилась увеличенная стоимость.

pre и post увеличение они определяются в Спецификации Языка Java (JLS) в двух разделах тех, которых я воспроизвожу переведенные части, которые значительные для этого вопроса (моя эмфаза):

  • 15.14.2:Operador Постустановленного Увеличения ++
    (. опущенный.)
    Во время выполнения, если оценка выражения завершается круто, тогда выражение постустановленного увеличения завершает круто for тот же разум и нет увеличения. В противоположном случае, стоимости 1 добавляется к стоимости переменной и сумма хранится в переменной. (... опущенный...) Стоимость выражения постустановленного увеличения - стоимость переменной до того, как хранилась новая стоимость.
    (. опущенный.)

  • 15.15.1. Оператор Увеличения Предопределил ++
    (. опущенный.)
    Во время выполнения, если оценка выражения завершается круто, тогда выражение уменьшения префикса завершает круто for тот же разум и нет увеличения. В противоположном случае, стоимости 1 добавляется к стоимости переменной и сумма хранится в переменной. (... опущенный...) Стоимость выражения постустановленного увеличения - стоимость переменной после того, как новая стоимость хранилась.
    (. опущенный.)

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

У всего этого нет никакой важности в коде как следующий:

for ( int n=1; n<10; ++n)
for ( int n=1; n<10; n++)

В этом коде, для той же стоимости n, выражения ++n и n++ они оцениваются в отличную стоимость, но это неуместное, так как эта стоимость не использована и единственное, у чего есть значительный эффект, - тот факт, что переменная увеличилась в 1, который происходит в обоих случаях. Оба цикла выполнят то же число повторений.

Но да это важно в коде как следующий:

int a; int b;
a = 3;
b = a++;
System.out.println( "a="+a + " b=" + b);
a = 3;
b = ++a; 
System.out.println( "a="+a + " b=" + b);

Где вывод:

a=4 b=3
a=4 b=4

В выражении b = a++ оценивается переменная a (что стоит 3), добавляет 1 к этой стоимости и результат суммы (4) хранится в переменной в. Результат выражения a++ это стоимость, у которой есть переменная a до того, как хранилась новая стоимость (которой было 3), с которым результат выражения a++ его 3. И это, 3, - то, что хранится в b.

В выражении b = ++a оценивается переменная a (что стоит 3), добавляет 1 к этой стоимости и результат суммы (4) хранится в переменной a. Результат выражения ++a это стоимость, у которой есть переменная a после того, как хранилась новая стоимость (которой 4), с которым результат выражения ++a его 4. И это, 4, - то, что хранится в b.

Продолжая estríctamente этот способ оценивать увеличение pre и постустановленный мы можем оценивать corréctamente любое выражение, в которое они были бы введены. Например:

    int a; int b;
    a = 3;
    b = ++a + a++;
    System.out.println( "a="+a + " b=" + b);
    a = 3;
    b = a++ + a++; 
    System.out.println( "a="+a + " b=" + b);

В первом выражении b закончи тем, что стой 8, потому что первый ++a оценивается 4 (стоимость, когда хранили увеличение) и для, когда работает второй a++ переменная a уже он содержит 4, увеличивается в 5 но стоимость выражения a++ это тот переменной перед тем, как увеличиваться, с которым оценивается 4. И 4+4=8.
Во втором выражении b закончи тем, что стой 7, потому что первый a++ оценивается 3 (стоимость перед тем, как хранить увеличение) и для, когда работает второй a++ переменная a уже он содержит 4, увеличивается в 5 но стоимость выражения a++ это тот переменной перед тем, как увеличиваться, с которым оценивается 4. И 3+4=7.

НО ЛУЧШЕ НЕ ДЕЛАТЬ ЭТО

Хотя мы поймем perféctamente, как функционируют операторы pre и post я увеличиваю использовать их в выражениях, которые не были бы тривиальными, только будешь служить для того, чтобы запутать. В тебя, в твоих сотрудников, в твоего координатора, в которого он проверяет код, в который он должен заниматься кодом 5 лет спустя, когда тот, кто написал это коту уже давно, что ушел из предприятия...

2
ответ дан 01.12.2019, 08:17