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