Yes, they are equivalent. The standard says in [atomics.ref.ops]:
T operator=(T desired) const noexcept;
Effects: Equivalent to:
store(desired);
return desired;
and
T load(memory_order order = memory_order::seq_cst) const noexcept;
Effects: Equivalent to: return load();
Note that both =
and the conversion function use std::memory_order::seq_cst
as a consequence, which is the safest memory order, but not the fastest due to the additional synchronization needed.
Why do we need both?
This is in part to create compatibility with C atomics. C11 added the _Atomic
qualifier, so you could write code such as:
_Atomic(int) x;
x = 0;
And exactly the same code would work nowadays in C++.
An explicit load
and store
is only necessary if you care about the memory order for performance reasons.
However, it is good practice to use load
and store
with a memory order consistently. This way, you can always express which memory order you intended to use. The operator overloads don't express this intent.
stop.load(std::memory_order_relaxed)
andstop.store(true, std::memory_order_relaxed);
should be fine here, as Serge says. You just need the store to be seen promptly, andrelaxed
still guarantees that. You only need a stronger ordering if you need to synchronize other data. – Antimere