-9

I'm having trouble understanding how Post Increment (++), Pre Increment work together in an example.

x++ means add 1 to the variable But I am confused with this example:

using namespace std;
/ run this program using the console pauser or add your own getch, system("pause") or input loop */
int main() {
    int a;
    a=8;
    cout<<++a<<a++<<endl;
    cout<<a<<endl;
    return 0;
}

I assume this means in first increased by 1 and in second it will first assign and then increment Which means the result should be 9 8 and 9 But when I compile it, I get 10 8 and 10. I don't understand.

  • Can you see the problem with a function call like `g(f(++a), a++)`? – Bathsheba Dec 09 '20 at 09:01
  • How do you increment 8 twice and get 9? – molbdnilo Dec 09 '20 at 09:08
  • if a = 8: `++a` => use 9 and remains 9 `a++` => use 8 and remains 9 – Alejandro Salamanca Mazuelo Dec 09 '20 at 13:45
  • see also [here](/q/65218593), [here](/q/65218062), [here](/q/65214679), [here](/q/65213547), [here](/q/65202047), [here](/q/65201319), [here](/q/65197004), [here](/q/65196430), [here](/q/65195800), [here](/q/65194855), [here](/q/65194558), [here](/q/65194446), [here](/q/65194438), [here](/q/65194193) – gnat Dec 10 '20 at 08:58

1 Answers1

1

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).
Cedric
  • 278
  • 1
  • 9
  • Or perhaps the downvoter merely took exception to your answering what could be the 10th version of this question in two days. Which in my opinion is not a good reason to downvote an answer. – Bathsheba Dec 09 '20 at 13:17
  • @Bathsheba Thanks for the feedback! If `f` and `g` return `int`, they would be chained though, not nested, right? Since `std::cout << f(a);` == `std::cout.operator(f(a));`. For custom types, that would be different. – Cedric Dec 09 '20 at 14:19
  • Yeah, probably true, I just noticed how many others there are, could just delete mine. – Cedric Dec 09 '20 at 14:19
  • @Bathsheba : Done. To be honest, now that I looked more into it, it's not clear to me why for the `int` case the order is not specified. After all, I would expect `std::cout << int(2) << int(3);` to be equal to `std::cout.operator(int(2)).operator(int(3));` even before C++17. For non-inbuilt types, that's a different story. – Cedric Dec 09 '20 at 16:04