I'm working in a project with C++11 and I tried following code
#include <atomic>
struct A {
std::atomic_int idx = 1;
};
int main() {
return 0;
}
I get the compiler error
error: use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
std::atomic_int idx = 1;
^
The same result is with C++14. When I switch to C++17 it works: wandbox
I checked cppreference for differences:
std::atomic
std::atomic<T>::operator=
std::atomic<T>::atomic
But there is no difference documented between C++14 and C++17. Why does it work with C++17 and not with C++14?
std::atomic is neither copyable nor movable. The compatibility macro _Atomic is provided in <stdatomic.
std::atomic compiles to lock addq . The LOCK prefix makes the following inc fetch, modify and update memory atomically. our explicit inline assembly LOCK prefix compiles to almost the same thing as std::atomic , except that our inc is used instead of add .
In order to solve this problem, C++ offers atomic variables that are thread-safe. The atomic type is implemented using mutex locks. If one thread acquires the mutex lock, then no other thread can acquire it until it is released by that particular thread.
Because in C++17 there is a guaranteed RVO. In C++14 statements like Foo x = Foo(args)
and Foo x (args)
are technically not the same, but they are in C++17.
struct Foo {
Foo() = default;
Foo(const Foo&) = delete;
};
int main() {
// Works in C++17 and C++20, fails in C++14 and before
Foo foo = Foo();
}
You can read more about this here: https://en.cppreference.com/w/cpp/language/copy_elision
In particular the section (since C++17)
:
T x = T(T(f())); // only one call to default constructor of T, to initialize x
To make C++14 code work, you can use
std::atomic_int idx { 1 };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With