Почему порядок оценки параметров функции неуточнен в С++?

В стандарте не указывается порядок оценки аргументов с помощью этой строки:

Порядок оценки аргументов не указан.

Что делает

Улучшенный код может быть сгенерирован при отсутствии ограничений на порядок оценки выражения

означает?

В чем заключается недостаток в запросе всех компиляторов для оценки аргументов функции слева направо? Какие виды оптимизации выполняют компиляторы из-за этой неопределенной спецификации?

Ответ 1

Разрешить компилятору переупорядочить оценку операндов, добавляет больше места для оптимизации.

Здесь приведен полный пример для иллюстрации.

Предположим, что процессор может:

  • Выпуск 1 инструкции за каждый цикл.
  • Выполнение добавления в 1 цикл.
  • Выполните умножение в 3 цикла.
  • Может выполнять дополнения и умножения одновременно.

Теперь предположим, что у вас есть вызов функции следующим образом:

foo(a += 1, b += 2, c += 3, d *= 10);

Если вы должны были выполнить это слева направо на процессоре без OOE:

Cycle - Operation
0     -    a += 1
1     -    b += 2
2     -    c += 3
3     -    d *= 10
4     -    d *= 10
5     -    d *= 10

Теперь, если вы разрешите компилятору переупорядочить их: (и сначала начать умножение)

Cycle - Operation
0     -    d *= 10
1     -    a += 1, d *= 10
2     -    b += 2, d *= 10
3     -    c += 3

Итак, 6 циклов против 4 циклов.

Снова это полностью надуманно. Современные процессоры намного сложнее. Но у вас есть идея.

Ответ 2

Вот простой пример. Предположим, что у вас есть вызов функции следующим образом:

// assume that p is a pointer to an integer
foo(*p * 3, bar(), *p * 3 + 1);

Компилятор должен разыменовать p дважды (и выполнить некоторые вычисления на основе результата) и вызвать bar один раз. Если компилятор умный, он может изменить порядок оценки на

int temp = *p * 3;
foo(temp, bar(), temp + 1);

Таким образом, он должен выполнять "разыменование, умножение на 3" только один раз. Это известно как устранение общего подвыражения.