6

Consider the code:

#include <atomic>
#include <iostream>

struct stru {
  int a{};
  int b{};
};

int main() {
  std::atomic<stru> as;
  auto s = as.load();
  std::cout << s.a << ' ' << s.b << std::endl;
}

Note that although stru has default member initializer, it still qualifies as an aggregate type since C++14. std::atomic has a trivial default constructor. According to the standard, should the members of as be initialized to zero? clang 6.0.0 doesn't do this (see here), while gcc 7.2.0 seems so (see here).

Lingxi
  • 14,579
  • 2
  • 37
  • 93

2 Answers2

4

Strictly speaking, I think both compilers are right, in that your program exhibits undefined behavior. To quote n4140 (C++14), [atomics.types.operations.req], emphasis mine:

In the following operation definitions:

  • an A refers to one of the atomic types.

[...]

A::A() noexcept = default;

Effects: leaves the atomic object in an uninitialized state. [ Note: These semantics ensure compatibility with C. — end note ]

as is uninitialized before the load. So the usual spiel about undefined behavior must follow.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    But one can do value/zero-initialization with `std::atomic as{}` and guarantee the members are zero, right? – Lingxi Mar 20 '18 at 14:59
  • 2
    @Lingxi - No. That consructor is defined as defaulted, with the specified effect of not doing initialization. Value initializing it is gonna call the same c'tor. – StoryTeller - Unslander Monica Mar 20 '18 at 15:02
  • 1
    But it's said on [cppref](http://en.cppreference.com/w/cpp/language/value_initialization) that *if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor*. So zero-initialization applies here, making constructors irrelevant. No? – Lingxi Mar 20 '18 at 15:07
  • @Lingxi - It would, if the standard did not explicitly demand otherwise, which it does. – StoryTeller - Unslander Monica Mar 20 '18 at 15:08
  • @Lingxi - Recall that the standard library types are not always subject to the same constraints as user defined types. For example, you can't create a non-empty `std::initializer_list`, except a non-empty one is created for you every time you use list initialization and so forth. – StoryTeller - Unslander Monica Mar 20 '18 at 15:11
  • 1
    I think the standard text you quoted only says about the trivial default constructor, but nothing about value-initialization. – Lingxi Mar 20 '18 at 15:11
  • @Lingxi - I'm afraid that's wishful thinking on your part. The standard text is clear, from the POV of the abstract machine, this is an uninitialized object. – StoryTeller - Unslander Monica Mar 20 '18 at 15:12
  • I cannot get it still. Please see [here](https://stackoverflow.com/q/49400942/1348273). – Lingxi Mar 21 '18 at 08:01
0

According to cppreference the std::atomic::atomic() constructor doesn't initialize the obj:

atomic() noexcept = default;

1) The default constructor is trivial: no initialization takes place other than zero initialization of static and thread-local objects. std::atomic_init may be used to complete initialization.

bolov
  • 72,283
  • 15
  • 145
  • 224