Я думаю, что это часть проекта стандарта относится к порядку оценки:
1.9 Выполнение программы
...
- Если не указано иное, вычисления операндов отдельных операторов и подвыражений отдельных выражений не упорядочены. Вычисление значения операндов оператора выполняется до вычисления значения результата оператора. Если побочный эффект на скалярном объекте не является последовательностью относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта, и они потенциально не параллельны, поведение не определено сильный>
а также:
5.2.2 Вызов функции
...
- [Примечание: вычисления постфиксного выражения и аргументов не упорядочены друг относительно друга. Все побочные эффекты вычислений аргументов упорядочены до входа в функцию — примечание в конце]
Итак, для вашей строки c.meth1(&nu).meth2(nu);
рассмотрим, что происходит в операторе с точки зрения оператора вызова функции для финального вызова meth2
, поэтому мы ясно видим разбивку на постфиксное выражение и аргумент nu
:
operator()(c.meth1(&nu).meth2, nu);
оценки постфиксного выражения и аргумента для финального вызова функции (т. е. постфиксного выражения c.meth1(&nu).meth2
и nu
) не упорядочены относительно друг друга в соответствии с вызовом функции правило выше. Таким образом, побочный эффект вычисления постфиксного выражения для скалярного объекта ar
не является последовательным по сравнению с оценкой аргумента nu
до вызова функции meth2
. В соответствии с приведенным выше правилом выполнение программы, это поведение undefined.
Другими словами, компилятору не требуется оценивать аргумент nu
для вызова meth2
после вызова meth1
— он может предположить, что побочные эффекты meth1
не влияют на оценку nu
.
Ассемблерный код, созданный выше, содержит следующую последовательность в функции main
:
- Переменная
nu
размещается в стеке и инициализируется 0.
- Регистр (в моем случае
ebx
) получает копию значения nu
.
- Адреса
nu
и c
загружаются в регистры параметров.
meth1
называется
- Регистр возвращаемого значения и ранее кэшированное значение
nu
в регистре ebx
загружаются в регистры параметров.
meth2
называется
Важно отметить, что на шаге 5 выше компилятор позволяет повторно использовать кешированное значение nu
из шага 2 в вызове функции meth2
. Здесь игнорируется возможность того, что nu
могло быть изменено вызовом meth1
— «неопределенное поведение» в действии.
ПРИМЕЧАНИЕ. Этот ответ существенно изменился по сравнению с его первоначальной формой. Мое первоначальное объяснение с точки зрения побочных эффектов вычисления операнда, не упорядочиваемого перед окончательным вызовом функции, было неверным, потому что это так. Проблема заключается в том, что вычисление самих операндов имеет неопределенную последовательность.
person
Smeeheey
schedule
16.05.2016
nu
,&nu
иc
в стек в указанном порядке, затем вызыватьmeth1
, помещать результат в стек, затем вызыватьmeth2
, в то время как основанное на регистрах соглашение о вызовах требует загрузкиc
и&nu
в регистры, вызоваmeth1
, загрузкиnu
в регистр, а затем вызоваmeth2
. - person Neil   schedule 17.05.2016