'Understanding behavior of trivial constructors in C++

I'm trying to understand how the following construction behaves differently across C++ standards, and what the guarantees are on elements a and b.

struct X {
    int a; 
    int b;
};

void func() {
X x(1); // (1) Works in c++2a only
X y{1}; // (2) Works in c++1z
}
c++


Solution 1:[1]

This has nothing to do with the default constructor being trivial, or really with the default constructor at all.

X y{1}; does aggregate-initialization which doesn't use any constructor, but instead initialized members of an aggregate (which your class is since it doesn't explicitly declare any constructors) directly one-by-one from the braced initializer list. The remaining members which are not explicitly given a value are value-initialized, which here means that b will be zero-initialized.

X x(1); can also initialize aggregates in the same way (with minor differences not relevant here) since C++20. Before that, non-empty parenthesized initializers would only try constructors. But there is no constructor that takes a single argument of type int in your class. There is only an implicitly-declared default constructor which takes no arguments and implicitly-declared copy and move constructors, which take references to a X as argument.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1