Является ли ++ x более эффективным, чем x ++ в Java?

В классе программирования профессор преподавал нам около x++ и ++x, причем x было целым числом.

Он сказал, что в сценарии мы можем просто поставить либо x++, либо ++x, ++x более эффективен (хотя, тем не менее, теоретически, более эффективно).

Но я забыл, почему. Кто-нибудь знает? Это было с Java.

Ответы

Ответ 1

Это не более эффективно в Java. Он может быть более эффективным на языках, где операторы increment/decment могут быть перегружены, но в остальном производительность точно такая же.

Разница между x++ и ++x заключается в том, что x++ возвращает значение x до того, как оно было увеличено, а ++x возвращает значение x после того, как оно было увеличено. С точки зрения генерации кода оба составляют то же самое количество инструкций, по крайней мере, когда вы можете использовать либо взаимозаменяемые (если вы не можете использовать их взаимозаменяемо, вы не должны беспокоиться о том, какой из них быстрее, вы должны быть выбрав тот, который вам нужен). Единственное различие заключается в том, где указана инструкция инкремента.

В С++ классы могут перегружать как префикс (++x), так и postfix (x++). При работе с типами, которые перегружают их, почти всегда быстрее использовать префиксный оператор, потому что семантика постфиксного оператора вернет копию объекта, как это было до приращения, даже если вы не использовали его, тогда как префикс-оператор может просто вернуть ссылку на измененный объект (и Бог знает, что разработчики на С++ предпочитают возвращать ссылки, а не копии). Это может послужить основанием для рассмотрения ++x, превосходящего x++: если вы привыкли использовать ++x, вы могли бы сэкономить некоторые незначительные проблемы с производительностью, когда/если вы переключитесь на С++. Но в контексте только Java, оба абсолютно эквивалентны.

Как и pst в комментариях выше, я никогда не использую возвращаемое значение x++ или ++x, и если вы этого не сделаете, вы, вероятно, должны просто придерживаться того, который вы предпочитаете.

Ответ 2

Из любопытства вы можете проверить сгенерированный байт-код.

Эта программа:

public static void main(String args[]) {
    int i = 1; //bytecode 0, 1
    i++; //bytecode 2
    ++i; //bytecode 5
    int a = ++i; //bytecode 8, 11, 12
    int b = i++; //bytecode 13, 14, 17
}

генерирует следующий байт-код:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iinc          1, 1
       5: iinc          1, 1
       8: iinc          1, 1
      11: iload_1
      12: istore_2
      13: iload_1
      14: iinc          1, 1
      17: istore_3
      18: return

Итак, вы можете видеть, что операторы pre и post fix строго идентичны с точки зрения байт-кода (кроме порядка операций).

Если и когда JIT компилирует эту часть вашего кода, все ставки отключены. Например, код выше, как есть, может быть скомпилирован как no-op, потому что он не имеет побочных эффектов.

Ответ 3

Реальная правда заключается в том, что *++x был быстрее, чем *x++ на PDP-11 и, возможно, VAX, потому что он скомпилирован в одну инструкцию (регистр автоинкремента отложен). Аналогично *x-- был быстрее, чем *--x. Использование любой формы без разыменования будет только быстрее в одном случае, а не в другом, если компилятор все еще сгенерировал эту инструкцию, которая была бы расточительной, потому что разыменование все равно произошло.

Те дни давно прошли.