Are uninitialized references zero-initialized and uninitialized scalars default-initialized?

Viewed 180

Are the following statements correct?

  • An uninitialized reference is considered zero-initialized.
  • An uninitialized scalar is considered default-initialized.
  • Any other uninitialized entity is not considered zero-initialized nor default-initialized.

They are based on [dcl.init.general/6] (bold emphasis mine):

To zero-initialize an object or reference of type T means:

  • if T is a scalar type, the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;
  • if T is a (possibly cv-qualified) non-union class type, its padding bits are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;
  • if T is a (possibly cv-qualified) union type, its padding bits are initialized to zero bits and the object's first non-static named data member is zero-initialized;
  • if T is an array type, each element is zero-initialized;
  • if T is a reference type, no initialization is performed.

and on [dcl.init.general/7] (bold emphasis mine):

To default-initialize an object of type T means:

  • 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]). The constructor thus selected is called, with an empty argument list, to initialize the object.
  • If T is an array type, each element is default-initialized.
  • Otherwise, no initialization is performed.
3 Answers

Are the following statements correct?

No, you are flipping the logical connections on their heads.

The definitions of "zero-initialization" and "default-initialization" specify what it means if something else in the standard says "the object is zero-initialized". When the standard says that, you use the definition of zero-initialization to see what it means. For a reference, it means no initialization is done. So a zero-initialized reference is uninitialized (and therefore ill-formed).

That does not imply the inverse though. An uninitialized reference is not zero-initialized. This is a fallacy: https://en.wikipedia.org/wiki/Affirming_the_consequent

A reference is zero-initialized when the standard says zero-initialization is performed.

(Several questions in the same questions: I will answer one)

Is the following statement correct?

  • An uninitialized reference is considered zero-initialized.

No. There is no such thing as an uninitialized reference, as it would need to refer to a variable or object, as opposed to a (reference type) parameter or a (reference type) return type, in which context initialization do not apply; as per [dcl.init.ref]/1 and /3:

/1 A variable whose declared type is “reference to T” ([dcl.ref]) shall be initialized.

/3 The initializer can be omitted for a reference only in a parameter declaration ([dcl.fct]), in the declaration of a function return type, in the declaration of a class member within its class definition ([class.mem]), and where the extern specifier is explicitly used.

Regarding the quoted [dcl.init.general]/6:

To zero-initialize an object or reference of type T means:

  • [...]
  • [...] if T is a reference type, no initialization is performed.

it refers to the cases where other parts of the standard governs that zero-initialization applies (and what is the effect of it for different entities); for initialization of a reference, particularly consider static initialization, as governed per [basic.start.static]/2:

[...] If constant initialization is not performed, a variable with static storage duration ([basic.stc.static]) or thread storage duration ([basic.stc.thread]) is zero-initialized ([dcl.init]). Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. All static initialization strongly happens before ([intro.races]) any dynamic initialization.

Such that static initialization of a reference type variable (which is not constant-initialized) will pertain solely of dynamic initialization, as the effect of the zero initialization of first step of static initialization is no initialization.

An uninitialized reference is considered zero-initialized.

It could be if the uninitialised reference has been zero-initialised. That said, there is no observable difference between an uninitialised reference that has been zero-initialised and an uninitialised reference that hasn't been zero-initialised.

An uninitialized scalar is considered default-initialized.

It could be if the uninitialised scalar has been default-initialised. That said, there is no observable difference between an uninitialised scalar that has been default-initialised and an uninitialised scalar that hasn't been default-initialised.

Any other uninitialized entity is not considered zero-initialized nor default-initialized.

An entity is considered to be zero-initialised after it has been zero-initialised and it's considered to be default-initialised after it has been default initialised.

Related