Among the overloaded operators the third one is the worst. It has a side effect that the original value of Integer is changed. For example, consider the followng code
1 2 3 4
|
Integer x( 10 ), y( 20 );
Integer z( 0 );
z = x + y;
|
It is natural to think that neither x nor y will be changed in the last statement. Consider an equivalent code where Integer is changed to fundamental type int
1 2 3 4
|
int x = 10, y = 20;
int z = 0;
z = x + y;
|
You will not assume that after the statement the value of x will be equal to 30, will you?
So in my opinion the best realization is the first one. It allows the compiler to apply optimization of the return value.
As for you last question then the following code is valid for fundamental types
1 2 3
|
int x;
( x = 10 ) += 10;
std::cout << "x = " << x << std::endl;
|
So user defined types shall follow the same convention.
EDIT: I am sorry. I thought that in the third operator there is expression
i
+= rv.i;
Instead you use
i + rv.i;
So the third operator is simply invalid because it does not do what is awaiting from it.
I suppose you meant i += rv.i that is it was a typo.