Reputation: 740
I can't seem to get the address of an atomic object after a store.
e.g.
std::atomic<int> i;
std::atomic<int>* p = &++i; // doesn't work
auto* p = &++i; // doesn't work
// below works:
++i;
auto* p = &i;
What's happening here and why?
To clarify: I know it returns an r-value. Why doesn't it return the original object, this
? Is this a purposeful design choice or was it an oversight?
More specifically, what's happening under-the-hood for this requirement?
Upvotes: 1
Views: 559
Reputation: 118681
While the pre-increment operator usually returns its operand by reference, in the case of std::atomic
integers, it returns the new value as a temporary. So in your example ++i
does not return a reference to the atomic<int> i
itself, it returns the new value of i
(i.e. an int). You can see this at: https://en.cppreference.com/w/cpp/atomic/atomic/operator_arith
It would be misleading and even dangerous to return a reference to the original atomic<int>
, because to access the int value through this reference would require a second, separate read operation — so its value might be different from the value at the time of increment. (This isn't particularly relevant your example code, since you are only trying to obtain a pointer to the referenced object, but some code will actually access the value after ++
so this is why returning a reference isn't possible.)
In other words, if ++i
returned a reference to the atomic<int> i
, then
int j = ++i;
would be equivalent to
++i;
// ...other threads may modify the value of `i` here!...
int j = i;
The whole point of atomics is to perform reads and writes together as an indivisible operation, so ++i
must internally use hardware/OS atomic operations to simultaneously read and increment the integer, so the new value is returned as a temporary.
If you're curious to see what's under the hood, here is libc++'s implementation where you can see that operator++
simply calls into fetch_add(1)
and returns the result + 1.
Upvotes: 6