c++initializationlanguage-lawyerobject-lifetime

Why is the concept of vacuous initialization necessary?


The concept of vacuous initialization is introduced and used at [basic.life/1], and it does not seem to be used anywhere else in the C++ standard:

The lifetime of an object or reference is a runtime property of the object or reference. A variable is said to have vacuous initialization if it is default-initialized and, if it is of class type or a (possibly multi-dimensional) array thereof, that class type has a trivial default constructor. The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),

Since vacuous initialization is a subset of default initialization, it is initialization for class and array types, and no initialization for scalar types (cf. [dcl.init.general/7]), and therefore both cases are covered by the phrase ‘initialization (if any)’.

So why is the concept of vacuous initialization necessary?

The quote seems equivalent to this amended version:

The lifetime of an object or reference is a runtime property of the object or reference. The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete ([dcl.init]),

Solution

  • The current draft standard, quoted by the OP, has reached its state via CWG issue 2256 (2256. Lifetime of trivially-destructible objects) and P1787R6 (P1787R6: Declarations and where to find them), after which, if any, the term (rather than "the concept") can be used to collective refer to cases where "initialization" will not suffice.

    At the very least, it is referred to from [stmt.dcl]/3:

    Upon each transfer of control (including sequential execution of statements) within a function from point P to point Q, all variables that are active at P and not at Q are destroyed in the reverse order of their construction. Then, all variables that are active at Q but not at P are initialized in declaration order; unless all such variables have vacuous initialization ([basic.life]), the transfer of control shall not be a jump. [...]

    Simply "initialization" does naturally not suffice here, as variable could have non-vacuous initialization such that a jump between point P to point Q would violate the restriction of [stmt.dcl]/3.

    If we were to amend [basic.life/1] as proposed, the term would no longer be defined, and e.g. [stmt.dcl]/3 would need to explicitly write out the full initialization contexts for where a jump (under the P->Q restrictions) is allowed.