It's not a shorthand.
The += symbol appeared in the C language about 20 years ago, and - with the C idea of "smart assembler" correspond to a clearly different machine instruction: += maps to INC, while + maps to ADD.
With a clean idea that the first is operating on x, while the second is evaluating an expression and later place the result in a given place.
Enabling compiler optimization the correspondence can be swapped based on convenience, but there is still a conceptual difference.
x += 5 means
- find the place identified by x
- add 5 to it,
but x = x + 5 means:
- evaluate x+5
- find the place identified by x
- copy x into an accumulator
- add 5 to the accumulator
- store the result in x
- find the place identified by x
- copy the accumulator to it.
Of course, optimization can
- if "finding x" has no side effects, the two "finding" can be done once (and x become an address stored in a pointer register)
- the two copy can be elided if the ADD is applied to
&x instead to the accumulator
thus making the optimized code to coincide the x += 5 one.
But this can be done only if "finding x" has no side effects, otherwise
*(x()) = *(x()) + 5;
and
*(x()) += 5;
are semantically different, since x() side effects will be produced twice or once.
The equivalence between x = x + y and x += y is hence due to the particular case where += and = are applied to a direct l-value.
[EDIT: Following Brendan Comment]
Yes, in the x86 family, ++ maps INC, += maps ADD() and + maps ADD
I'm not referring to any specific assembly language, but to an aspect of processors architetcures:
Every CPU has an ALU (aritmetic-logical unit) that is -in its very essence- a combinatorial network whose inputs and output are "plugged" to registry and / or memory depending on the opcode of the instruction
Bynary operation are typically implemented as "modifier of an accumulator register with an input taken "somewere", where somewhere can be
- inside the instruction flow itself (typical for manifest contant: ADD A 5)
- inside another registry (typycal for expression conputation with temporaries: es ADD A B)
- inside the memory, at an address given by a register (typical of data fetching es: ADD A (H)) - H, in this case, work like a dereferencing pointer.
With this pseudocode, x+=5 is
ADD (X) 5
while x = x+5 is
MOVE A (X)
ADD A 5
MOVE (X) A
That is x+5 gives a temporary that is later assigned. x+=5 operates directly on x.
The actual implementation depends on the real instruction set of the processor:
If there is no ADD (.) c the first code becomes the second.
If there is and optimization are enabled the second code become the first.