Order of evaluation

From Cppreference

Jump to: navigation, search

Order of evaluation of the operands of any C++ operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified (except where noted below). The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.

There is no concept of left-to-right or right-to-left evaluation in C++, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression a + b + c is parsed as (a + b) + c due to left-to-right associativity of operator+, but the subexpression c may be evaluated first (or last, or at the same time as a or b) at run time.

Contents

[edit] Sequenced-before rules(since C++11)

[edit] Definitions

[edit] Evaluations

There are two kinds of evaluations performed by the compiler for each expression or subexpression (both of which are optional):

[edit] Ordering

"sequenced-before" is an asymmetric, transitive, pair-wise relationship between evaluations within the same thread (it may extend across threads if atomic types are involved with suitable std::memory_order).

[edit] Rules

1) Each value computation and side effect of a full expression (an expression that is not part of another expression, typically one that ends with a semicolon) is sequenced before each value computation and side effect of the next full expression.

2) The value computations (but not the side-effects) of the operands to any operator are sequenced before the value computation of the result of the operator (but not its side-effects).

3) When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.

4) The value computation of the built-in postincrement and postdecrement operators is sequenced before its side-effect.

5) The side effect of the built-in preincrement and predecrement operators is sequenced before its value computation (implicit rule due to definition as compound assignment)

6) Every value computation and side effect of the first (left) argument of the built-in logical AND operator && and the built-in logical OR operator || is sequenced before every value computation and side effect of the second (right) argument.

7) Every value computation and side effect associated with the first expression in the logicalĀ :? operator is sequenced before every value computation and side effect associated with the second or third expression.

8) The side effect (modification of the left argument) of the built-in assignment operator and of all built-in compound assignment operators is sequenced after the value computation (but not the side effects) of both left and right arguments, and is sequenced before the value computation of the assignment expression (the value is the reference it returns)

9) Every value computation and side effect of the first (left) argument of the built-in comma operator is sequenced before every value computation and side effect of the second (right) argument.

10) In list-initialization, every value computation and side effect of a given initializer clause is sequenced before every value computation and side effect associated with any initializer clause that follows it in the comma-separated list of the initializer list.

11) A function call that is not sequenced before or sequenced after another function call is indeterminately sequenced (CPU instructions that constitute different function calls cannot be interleaved, even if the functions are inlined)

12) The call to the allocation function (operator new) is indeterminately sequenced with respect to the evaluation of the constructor arguments in a new-expression

[edit] Undefined behavior

1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior (but i = ++i + 1; is well-defined)
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior

2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

cout << i << i++; // undefined behavior
a[i] = i++; // undefined bevahior

[edit] Sequence point rules(until C++11)

[edit] Definitions

Evaluation of an expression might produce side effects, which are: accessing an object designated by a volatile lvalue, modifying an object, calling a library I/O function, or calling a function that does any of those operations.

A sequence point is a point in the execution sequence where all side effects from the previous evaluations in the sequence are complete, and no side effects of the subsequent evaluations started.

[edit] Rules

1) There is a sequence point at the end of each full expression (typically, at the semicolon)

2) When calling a function (whether or not the function is inline and whether or not function call syntax was used), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body

3) There is a sequence point after the copying of a returned value of a function and before the execution of any expressions outside the function.

4) Once the execution of a function begins, no expressions from the calling function are evaluated until execution of the called function has completed (functions cannot be interleaved)

5) In the evaluation of each of the following four expressions, using the built-in (non-overloaded) operators, there is a sequence point after the evaluation of the expression a.

a && b
a || b
a ? b : c
a , b

[edit] Undefined behavior

1) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression.

i = ++i + i++; // undefined behavior
i = i++ + 1; // undefined behavior
i = ++i + 1; // undefined behavior (well-defined in C++11)
++ ++i; // undefined behavior (well-defined in C++11)
f(++i, ++i); // undefined behavior
f(i = -1, i = -1); // undefined behavior

2) Between the previous and next sequence point , the prior value of a scalar object that is modified by the evaluation of the expression, shall be accessed only to determine the value to be stored.

cout << i << i++; // undefined behavior
a[i] = i++; // undefined bevahior

Note: except for the sequence point at function return, evaluation order in C++ before C++11 is the same as the evaluation order used by the C programming language.


[edit] See also

Operator precedence which defines how expressions are built from their source code representation.