Если у нас есть три функции (foo, bar и baz), которые составлены так...
foo(bar(), baz())
Есть ли какая-либо гарантия по стандарту С++, который будет оцениваться баром до baz?
Если у нас есть три функции (foo, bar и baz), которые составлены так...
foo(bar(), baz())
Есть ли какая-либо гарантия по стандарту С++, который будет оцениваться баром до baz?
Нет, нет такой гарантии. Он не определен в соответствии со стандартом C++.
Бьярне Страуструп также прямо говорит об этом в "Языке программирования C++" в разделе 6.2.2 третьего издания с некоторыми соображениями:
Улучшенный код может быть сгенерирован при отсутствии ограничений на порядок оценки выражений
Хотя технически это относится к более ранней части того же раздела, где говорится, что порядок оценки частей выражения также не определен, т.е.
int x = f(2) + g(3); // undefined whether f() or g() is called first
Нет никакого определенного порядка для bar() и baz() - единственное, что Стандарт говорит, что они оба будут оценены до вызова foo(). Из стандарта С++, раздел 5.2.2/8:
Порядок оценки аргументов не указано.
Из [5.2.2] Вызов функции
Порядок оценки аргументов неуточнен. Все побочные эффекты оценок выражения аргументов вступают в силу до ввода функции.
Поэтому нет гарантии, что bar()
будет выполняться до baz()
, только bar()
и baz()
будут вызваны до foo
.
Также обратите внимание на [5] Выражения, что:
за исключением случаев, отмеченных [например, специальные правила для
&&
и||
], порядок оценки операндов отдельных операторов и подвыражений отдельных выражений и порядок, в котором происходят побочные эффекты, не определены.
так что даже если бы вы спрашивали, будет ли bar()
работать до baz()
в foo(bar() + baz())
, порядок все еще не указан.
С++ 17 задает порядок оценки для операторов, которые были неопределены до С++ 17. См. Вопрос Каковы гарантии порядка оценки, введенные С++ 17? Но обратите внимание на ваше выражение
foo(bar(), baz())
имеет неуказанный порядок оценки.
В С++ 11 соответствующий текст можно найти в 8.3.6 Аргументы по умолчанию /9 (Emphasis mine)
Аргументы по умолчанию оцениваются каждый раз при вызове функции. Порядок оценки аргументов функции не указан. Следовательно, параметры функции не должны использоваться в аргументе по умолчанию, даже если они не оцениваются.
То же словоблудие используется также стандартом С++ 14 и находится в в том же разделе.
Как уже отмечалось ранее, стандарт не дает никаких указаний относительно порядка оценки для этого конкретного сценария. Затем этот порядок оценки передается компилятору, и у компилятора может быть гарантия.
Важно помнить, что стандарт С++ - это действительно язык для инструктирования компилятора о построении сборки/машинного кода. Стандарт - это только одна часть уравнения. В тех случаях, когда стандарт является неоднозначным или конкретно определенная реализация, вы должны обратиться к компилятору и понять, как он переводит инструкции С++ в настоящий машинный язык.
Итак, если порядок оценки является требованием или, по крайней мере, важным и совместимым с кросс-компилятором, не является обязательным требованием, исследуйте, как ваш компилятор в конечном итоге сочтет это вместе, ваш ответ может окончательно лежать там. Обратите внимание, что компилятор может изменить его методологию в будущем