You can think of:
cout << a++ << a;
As:
std::operator<<(std::operator<<(std::cout, a++), a);
C++ guarantees that all side effects of previous evaluations will have been performed at sequence points. There are no sequence points in between function arguments evaluation which means that argument a
can be evaluated before argument std::operator<<(std::cout, a++)
or after. So the result of the above is undefined.
C++17 update
In C++17 the rules have been updated. In particular:
In a shift operator expression
E1<<E2
andE1>>E2
, every value computation and side-effect ofE1
is sequenced before every value computation and side effect ofE2
.
Which means that it requires the code to produce result b
, which outputs 01
.
See P0145R3 Refining Expression Evaluation Order for Idiomatic C++ for more details.