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?

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
pankaj
  • 335
  • 4
  • 15
  • Nearly a duplicate of [How to initialize a static std::atomic data member](https://stackoverflow.com/q/20453054/5740428) – Jan Schultke Sep 01 '23 at 13:31

2 Answers2

8

Try:

std::atomic_int turnX(5);

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

Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • but why would `atomic_int turnX = 5;` not invoke that constructor ? Any quotes from the standard? – smerlin Jul 16 '11 at 13:19
  • 1
    @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. –  Jul 18 '11 at 00:22
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.

Amit
  • 645
  • 1
  • 3
  • 19