Search code examples
c++initializationlanguage-lawyerstdatomic

Why does default constructor of std::atomic not default initialize the underlying stored value?


Since it's Thanksgiving today in the USA, I'll be the designated turkey to ask this question:

Take something as innocuous as this. An atomic with a simple plain old data type such as an int:

atomic<int> x;
cout << x;

The above will print out garbage (undefined) data. Which makes sense given what I read for the atomic constuctor:

(1) default constructor

Leaves the atomic object in an uninitialized state. An uninitialized atomic object may later be initialized by calling atomic_init.

Feels like an odd committee decision. But I'm sure they had their reasons. But I can't think of another std:: class where the default constructor will leave the object in an undefined state.

I can see how it would make sense for more complex types being used with std::atomic that don't have a default constructor and need to go the atomic_init path. But the more general case is to use an atomic with a simple type for scenarios such as reference counting, sequential identifier values, and simple poll based locking. As such it feels weird for these types to be not have their own stored value "zero-initialized" (default initialized). Or at the very least, why have a default constructor if isn't going to be predictable.

What's the rationale for this where an uninitialized std::atomic instance would be useful.


Solution

  • As mentioned in P0883, the main reason for this behavior is compatibility with C. Obviously C has no notion of value initialization; atomic_int i; performs no initialization. To be compatible with C, the C++ equivalent must also perform no initialization. And since atomic_int in C++ is supposed to be an alias for std::atomic<int>, then for full C/C++ compatibility, that type too must perform no initialization.

    Fortunately, C++20 looks to be undoing this behavior.