Copy-initialization of atomic variables in C++11
Asked Answered
L

2

5

Can atomic variables in C++11 be initialized globally?

For example:

std::atomic_int turnX = 5;
int main() {
    /* ... */
}

This fails with:

error: deleted function ‘std::atomic<int>::atomic(const std::atomic<int>&)’

Looking at <atomic>, it does give an idea that this is not allowed. Am I correct in making a statement that atomic variables can be assigned values only from within a function?

Latex answered 14/7, 2011 at 22:38 Comment(1)
Nearly a duplicate of How to initialize a static std::atomic data memberSensual
F
9

Try:

std::atomic_int turnX(5);

This uses a constexpr constructor, so it should be constructed as constant initialization (i.e. at load time).

Filler answered 14/7, 2011 at 23:9 Comment(2)
but why would atomic_int turnX = 5; not invoke that constructor ? Any quotes from the standard?Bugger
@smerlin: I imagine because it uses copy-initialisation. What might be happening is the 5 is being implicitly converted into an atomic_int and then turnX is copy-constructed from a non-constexpr object.Holloman
S
3

std::atomic variable (since it is not copyable or movable) can only be initialized using direct-initialization.

std::atomic_int turnX = 5; will only compile and run on a C++17 compiler or higher. Explanation:

// Prior to C++17
std::atomic_int turnX = 5; // Copy initialization => Compilation error.
std::atomic_int turnX(5); // Direct initialization.
std::atomic_int turnX{ 5 }; // Direct initialization.

Prior to C++17, the copy-initialization std::atomic_int turnX = 5; would first construct a temporary std::atomic_int from 5 and then direct-initialize turnX from that temporary. Without a move or copy constructor this would fail and so the line doesn't compile. std::atomic_int turnX (5); or std::atomic_int turnX {5}; however, is directly initialized by a constructor call with 5 as argument.

// C++17 or higher
std::atomic_int turnX = 5; // Direct initialization.
std::atomic_int turnX(5); // Direct initialization.
std::atomic_int turnX{ 5 }; // Direct initialization.

In C++17 or higher, the temporary is no longer created. Instead, turnX is directly initialized by a constructor call with 5 as argument. So, there is no issue with std::atomic_int being not copyable or movable.

Skewer answered 31/8, 2023 at 11:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.