In C++17, consider a case where S
is a struct with a deleted default constructor and a float member, when S is initialized with empty braces, is the float member guaranteed by the standard to be zero-initialized?
struct A {
int x{};
};
struct S
{
S() = delete;
A a;
float b;
};
int main()
{
auto s = S{}; // Is s.b guaranteed to be zero?
}
In my opinion, cppreference.com is not clear, saying both that:
If the number of initializer clauses is less than the number of members and basesor initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) copy-initialized from empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
(from here), which implies that b is guaranteed to be zero
In all cases, if the empty pair of braces {} is used and T is an aggregate type, aggregate-initialization is performed instead of value-initialization.
which implies that b is not guaranteed to be zero.
There is also a discussion that seems to imply that while not guaranteed, all known compiler zero-initialize anyway:
The standard specifies that zero-initialization is not performed when the class has a user-provided or deleted default constructor, even if that default constructor is not selected by overload resolution. All known compilers performs additional zero-initialization if a non-deleted defaulted default constructor is selected.