Your confusion has nothing to do with the pre- and post-increment, but with the evaluation order of the operator <<
. There are plenty of threads on this, here is a good one imho: SO discussion about evaluation order
The summary is :
- Before C++17, if you have an expression such as
std::cout << f(a) << g(a) << std::endl;
, the order of evaluation (f
first or g
first) is not specified.
This becomes clearer when we look at what the expression above means. For the overloaded operator<<
, it effectively becomes
operator<<(operator<<(std::cout, f(a)), g(a));
so:
function (<--------- arg 1 --------->,<arg2>)
In this case, the evaluation is unsequenced, and it is not defined whether arg1 or arg2 will be evaluated first.
- With C++17, the order is specified from left to right.
From [n4659] §8.2.2 : 5
If an operator function is invoked using operator notation, argument evaluation is sequenced as specified for the built-in operator.
I interpret this as follows: even if the operator is overloaded, if it is called as an operator (i.e. std::cout << f(a) << g(a) << std::endl;
), it will effectively be evaluated as
std::cout.operator<<(f(a)).operator<<(g(a)).operator<<(std::endl);
However, if the call is made explicitely as
operator<<(operator<<(std::cout, f(a)), g(a));
it will be treated as a function call and the order is still not specified.
- To be safe, you are better off splitting up your prints/evaluations in separate statements (i.e. separated by
;
) unless you have a good reason not to (and know the details well), especially since different operators behave differently (e.g. +
remains unsequenced after C++17).