Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@EricWF
Last active July 10, 2018 23:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EricWF/1590062a948279ff4937eafb030e74d7 to your computer and use it in GitHub Desktop.
Save EricWF/1590062a948279ff4937eafb030e74d7 to your computer and use it in GitHub Desktop.
Fixes for the specification of default-initialization and value-initialization.

Unify the behavior of value-initialization and default-initialization.

Introduction

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.

Proposed Changes

Make the following changes to [dcl.init]. These changes were written against a copy of the standard generated on 2018-07-06.

9.3 Initializers [dcl.init]

[...]

  • 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 calledThe 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.
  • 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.

Acknowledgements

  • Richard Smith for providing the initial wording and direction.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment