Ответ 1
Ответ зависит от того, какую версию стандарта C++ вы используете (или ваш компилятор).
C++ 2003 5.2.2 p8 сказал:
Порядок оценки аргументов не уточняется. Все побочные эффекты при оценке выражений аргументов вступают в силу до входа в функцию. Порядок вычисления выражения postfix и списка выражений аргументов не определен.
Это означает, что между оценкой f(x)
и args
нет точки последовательности.
В C++ 2011 вся концепция точек последовательности была заменена (см. N1944), и эта формулировка теперь просто примечание:
[Примечание: оценки выражения postfix и выражений аргумента не являются последовательными по отношению друг к другу. Все побочные эффекты при оценке выражений аргументов секвенируются до входа в функцию (см. 1.9). - конец примечания]
и 1.9 p15 говорит
При вызове функции (независимо от того, является ли функция встроенной), каждое вычисление значения и побочный эффект, связанные с любым выражением аргумента или с выражением постфикса, обозначающим вызываемую функцию, упорядочиваются перед выполнением каждого выражения или оператора в теле вызываемая функция. [Примечание: вычисления значений и побочные эффекты, связанные с различными выражениями аргументов, не являются последовательными. - конец примечания]
Это говорит о том, что выражение f(x)
и args
выражения упорядочены перед всем в теле g
, но они не упорядочены относительно друг друга, что соответствует правилам C++ 03, но сформулировано по-разному.
C++ 14 имеет те же правила, что и C++ 11, но, как отмечено в комментарии ниже, правила изменились в C++ 17.
C++ 2017 8.2.2 [expr.call] p5 говорит:
Постфиксное выражение упорядочивается перед каждым выражением в списке выражений и любым аргументом по умолчанию. Инициализация параметра, включая каждое связанное с ним вычисление значения и побочный эффект, определяется неопределенным образом относительно последовательности любого другого параметра.
Для вашего примера это означает, что следующие шаги выполняются по порядку:
-
f
оценивается. -
x
вычисляется и параметрыf
инициализируются. - Вызов функции
f(x)
оценивается. -
f(x)->g
оценивается. -
args
и другие аргументыg
вычисляются, и параметрыg
инициализируются (в неуказанном порядке). - Наконец, выполняется вызов функции
f(x)->g(args,...)
.