Currently default-initialization and value-initialization act bizzarely compared to each other. Specifically default-initialization is required to call trivial constructors when value-initialization is not.
For example:
struct T { int x; };
// default_init is initialized by a call to the trivial default ctor.
auto *default_init = new T;
// value_init is zero-initialized. The default ctor is not called.
auto *value_init = new T();
This causes undesirable behavior when a variable of type T
is declared with static or thread storage duration and no initializer, since T
is made to have a dynamic-initializer which invokes a trivial constructor that has no effect. In such scenarios T
should be considered fully-initialized during static-initialization. Note that in such cases the variable cannot be value-initialized because the syntax T t()
is not allowed.
In short zero-initialization plus default-initialization should be equivalent to value-initialization. Unfortunatly as it stands now it is not.
This behavior can be observed using the proposed [[constinit]]
attribute.
[[constinit]] int x; // OK, zero-initialized with no dynamic-initializer.
struct T { int x; };
[[constinit]] T t; // Fails! zero-initialized, then needlessly *default-initialized* during dynamic initialization.
Make the following changes to [dcl.init]. These changes were written against a copy of the standard generated on 2018-07-06.
[...]
-
7 To default-initialize an object of type
T
means:- 7.1 --- If T is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]).If the selected constructor is trivial, no initialization is performed. Otherwise the selected constructor is called
The constructor thus selected is called, with an empty argument list, to initialize the object. - 7.2 -- If T is an array type, each element is default-initialized.
- 7.3 -- Otherwise, no initialization is performed.
- 7.1 --- If T is a (possibly cv-qualified) class type ([class]), constructors are considered. The applicable constructors are enumerated ([over.match.ctor]), and the best one for the initializer () is chosen through overload resolution ([over.match]).If the selected constructor is trivial, no initialization is performed. Otherwise the selected constructor is called
-
8 To value-initialize an object of type T means:
- 8.1 --- the object is zero-initialized unless T is a class type ([class]) with a user provided or deleted default constructor or array thereof, then
- 8.2 --- the object is default initialized
8.1 --- if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;8.2 --- if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;8.3 --- if T is an array type, then each element is value-initialized;8.4 --- otherwise, the object is zero-initialized.
- Richard Smith for providing the initial wording and direction.