The assignment operators for the built in types return an lvalue
in C++ (unlike in C). But you cannot use it to modify the
object without an intervening sequence point, so your example is
undefined behavior (in C++03—C++11 changed a lot here, and
I seem to remember that one of the results made your code
defined).
Regardless of the situation with regards to undefined behavior,
you would be better off writing:
x = 2 * x + y;
It's far more readable. The fact that the assignment operators
result in lvalues is really only usable when the results are
bound immediately to a reference:
T&
SomeClass::f()
{
// ...
return aTinSomeClass += 42;
}
And even then, I'd write it in two statements.
(The general rule in C++ is that if the result of an operator
corresponds to the value of an object in memory, then it is an
lvalue. There was no general rule in C.)