See also this question and my answer to it. I'm not going to vote to close this as a duplicate because you're asking about C++ rather than C, but I believe the issue is the same in both languages.
the prior value shall be accessed only to determine the value to be stored.
This does seem like an odd requirement; why should the standard care why a value is accessed? It makes sense when you realize that if the prior value is read to determine the value to be stored in the same object, that implicitly imposes an ordering on the two operations, so the read has to happen before the write. Because of that ordering, the two accesses to the same object (one read and one write) are safe. The compiler cannot rearrange (optimize) the code in a way that causes them to interfere with each other.
On the other hand, in an expression like
a[i] = i++
there are three accesses to i
: a read on the left hand side to determine which element of a
is to be modified, a read on the right hand side to determine the value to be incremented, and a write that stores the incremented value back in i
. The read and write on the RHS are ok (i++
by itself is safe), but there's no defined ordering between the read on the LHS and the write on the RHS. So the compiler is free to rearrange the code in ways that change the relationship between those read and write operations, and the standard figuratively throws up its hands and leaves the behavior undefined, saying nothing about the possible consequences.
Both C11 and C++11 change the wording in this area, making some ordering requirements explicit. The "prior value" wording is no longer there. Quoting from a draft of the C++11 standard, 1.9p15:
Except where noted, evaluations of operands of individual operators
and of subexpressions of individual expressions are unsequenced. [...]
The value computations of the operands of an operator are sequenced
before the value computation of the result of the operator. If a side
effect on a scalar object is unsequenced relative to either
anotherside effect on the same scalar object or a value computation
using the value of the same scalar object, the behavior is undefined.