To explain what's going on here, let's make things much simpler: cout<<2*2+1*1;
. What happens first, 2*2 or 1*1? One possible answer is 2*2 should happen first, since it's the leftmost thing. But the C++ standard says: who cares?! After all, the result is 5 either way. But sometimes it matters. For instance, if f
and g
are two functions, and we do f()+g()
, then there is no guarantee which gets called first. If f
prints a message, but g
exits the program, then the message may never be printed. In your case, i[2]
got called before i[0]
, because C++ thinks it doesn't matter. You have two choices:
One option is to change your code so it doesn't matter. Rewrite your []
operator so that it doesn't change the Int
, and returns a fresh Int
instead. This is probably a good idea anyway, since that will make it consistent with 99% of all the other []
operators on the planet. It also requires less code:
Int &operator[](int x) { return this->v + x;}
.
Your other option is to keep your []
the same, and split your printing into two statements:
cout<<i[0]; cout<<i[2];
Some languages actually do guarantee that in 2*2+1*1
, the 2*2 is done first. But not C++.
Edit: I was not as clear as I hoped. Let's try more slowly. There are two ways for C++ to evaluate 2*2+1*1
.
Method 1: 2*2+1*1 ---> 4+1*1 ---> 4+1 --->5
.
Method 2: 2*2+1*1 ---> 2*2+1 ---> 4+1 --->5
.
In both cases we get the same answer.
Let's try this again with a different expression: i[0]+i[2]
.
Method 1: i[0]+i[2] ---> 2+i[2] ---> 2+4 ---> 6
.
Method 2: i[0]+i[2] ---> i[0]+4 ---> 4+4 ---> 8
.
We got a different answer, because the []
has side effects, so it matters whether we do i[0]
or i[2]
first. According to C++, these are both valid answers. Now, we are ready to attack your original problem. As you will soon see, it has almost nothing to do with the <<
operator.
How does C++ deal with cout << i[0] << i[2]
? As before, there are two choices.
Method 1: cout << i[0] << i[2] ---> cout << 2 << i[2] ---> cout << 2 << 4
.
Method 2: cout << i[0] << i[2] ---> cout << i[0] << 4 ---> cout << 4 << 4
.
The first method will print 24 like you expected. But according to C++, method 2 is equally good, and it will print 44 like you saw. Notice that the trouble happens before the <<
gets called. There is no way to overload <<
to prevent this, because by the time <<
is running, the "damage" has already been done.