Prior to C++17, in the line:
cout << g(g(x, y), y) << ' ' << x << ' ' << y << endl;
the value stored in x
and y
for the latter part of the expression could each either be read before or after or in between the calls to g
.
Note that the expressions y
in the argument list for g
do not read the stored value: y
is an lvalue being bound directly to an lvalue reference function parameter, so there is no lvalue-to-rvalue conversion.
The calls to g
have the following behaviour, where x
and y
refer to the variables in main
:
- Initial:
x = 5, y = 2
.
- After inner call to
g
: x = 5, y = 7
(call returns 13
).
- After outer call to
g
: x = 5, y = 20
(call returns 34
).
So the output will start with 34 5
, but the last number could either be 2
, 7
or 20
. This is known as unspecified behaviour.
Since C++17, the operands of a <<
chain are sequenced from left to right; the only possible output now is 34 5 20
.
Note: Some comments claimed there is undefined behaviour, however there is not. In C++03 terminology, there is a sequence point on entry and exit of a function call; the modification of y
in the function is separated from the read of y
in main
by one of those sequence points. In C++11 the sequencing is the same but the terminology changed. See point 11 here.