2

Below code snippet is From Herb Sutter's blog here

g++ outputs 10. MSVC also does output 10. Output could be different on different compilers.

I fail to understand how variable i is incremented. Can anyone explain me how come output is 10, Is 10 really correct output?

#include <iostream>
#include <vector>
#include <string>

int main()
{    
    std::vector<int> v = { 0, 0 };
    int i = 0;
    v[i++] = i++;
    std::cout << v[0] << v[1] << std::endl;
}
g24l
  • 3,055
  • 15
  • 28
user1
  • 4,031
  • 8
  • 37
  • 66

2 Answers2

1

EDITED

We'll leave the discussion of undefined behaviour out, and just focus on how your program arrives at the specified output.

First of all, lets state a fact:

  • i++ will increment the value of i, but return the original value that i held before being incremented.

from What is the difference between ++i and i++?.

Now, the line

v[i++] = i++;

evaluates, in your case, in the order "LHS" -> "RHS" -> assignment:

  • LHS, v[i++]: i is incremented to 1 and i++ returns 0 to v[i++].
  • RHS, i++: i now has value 1, but is incremented to 2, however i++ of RHS return 1.
  • Assignment: From above, the assignment results in: v[0] = 1 (after which i has value 2).

Hence, printing v[0] and v[1] will evaluate in 1 (updated value) and 0 (as initialised), respectively.

Community
  • 1
  • 1
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • Very nice approach to just explaining what goes on in the specific case, i reverted my dv! thumbs up. – g24l Dec 07 '15 at 12:54
  • Thanks! I hope the two downvoters on your answer will also reconsider after your edit, I think it's an relevant answer as well. – dfrib Dec 07 '15 at 13:22
  • well they were right to dv at start, was not actually clear to me what was asked! – g24l Dec 07 '15 at 13:24
-1

This is a problem of order of execution and it is undefined due to c++11:

5.17 Assignment and compound assignment operators

The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. The result in all cases is a bit-field if the left operand is a bit-field. In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

Simply put, the modification of the left argument is sequenced after the value computation, but not of the side-effects of the computation, of both sides and before returning the reference to the object.

So the actions to be taken are

A. evaluate left side ( return value of expression i++ = 0 )

B. return reference to object ( return reference to object of expression v[i++] )

C. compute side-effects for left side i.e. i-> 1

D. compute side-effects for right side i.e. i-> 2

As you can see from the rule above it is not clear if the order is ABCD or if it should be ACBD , since the order of the side-effects computation is not defined, if it should happen first for the left side or first for the right-side.

g24l
  • 3,055
  • 15
  • 28