В C ++ есть только несколько операторов, которые гарантируют порядок оценки
operator &&
сначала оценивает левый операнд, а если значение логически false
, тогда он избегает вычисления правого операнда. Типичное использование, например, if (x > 0 && k/x < limit) ...
, которое позволяет избежать деления на ноль.
operator ||
сначала вычисляет левый операнд, а если значение логически true
, тогда он избегает вычисления правого операнда. Например, if (overwrite_files || confirm("File existing, overwrite?")) ...
не будет запрашивать подтверждения, если установлен флаг overwrite_files
.
operator ,
сначала вычисляет левый операнд, а затем правый операнд, возвращая значение правого операнда. Этот оператор используется не очень часто. Обратите внимание, что запятые между параметрами в вызове функции являются , а не операторами запятых, и порядок вычисления не гарантируется.
Тернарный оператор x?y:z
сначала вычисляет x
, а затем в зависимости от логического значения результата оценивает только y
или только z
.
Для всех остальных операторов порядок оценки не указан.
Ситуация на самом деле хуже, потому что дело не в том, что порядок не указан, а в том, что вообще нет "порядка" для выражения, например, в
std::cout << f() << g() << x(k(), h());
возможно, что функции будут вызываться в порядке h-g-k-x-f
(это немного беспокоит, потому что ментальная модель оператора <<
как-то передает идею последовательности, но в действительности учитывает последовательность только в результатах порядка. в потоке, а не в порядке вычисления результатов).
Очевидно, что зависимости значений в выражении могут вводить некоторую гарантию заказа; например, в вышеприведенном выражении гарантируется, что оба k()
и h()
будут вызваны до x(...)
, потому что возвращаемые значения из обоих необходимы для вызова x
.
Обратите внимание, что гарантии для &&
, ||
и ,
действительны только для предопределенных операторов. Если вы перегрузите эти операторы для ваших типов, они будут в этом случае похожи на обычные вызовы функций, и порядок вычисления операндов будет не определен.