Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does std::atomic constructor behave different in C++14 and C++17

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?

like image 469
Thomas Sablik Avatar asked Dec 05 '19 14:12

Thomas Sablik


People also ask

Is STD atomic copyable?

std::atomic is neither copyable nor movable. The compatibility macro _Atomic is provided in <stdatomic.

What does std :: atomic do?

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 .

Is atomic thread safe C++?

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.


1 Answers

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 };
like image 143
Rinat Veliakhmedov Avatar answered Oct 12 '22 19:10

Rinat Veliakhmedov