Default-initialization - cppreference.com

From cppreference.com

This is the initialization performed when an object is constructed with no initializer.

Syntax

T object;(1) newT(2) Explanation

Default-initialization is performed in three situations:

1) when a variable with automatic, static, or thread-local

storage duration

is declared with no initializer;

2) when an object with dynamic storage duration is created by a

new-expression

with no initializer;

3) when a base class or a non-static data member is not mentioned in a

constructor initializer list

and that constructor is called.

The effects of default-initialization are:

if T is a (possibly cv-qualified) non-POD(until C++11) class type, the constructors are considered and subjected to

overload resolution

against the empty argument list. The constructor selected (which is one of the

default constructors

) is called to provide the initial value for the new object;

if T is an array type, every element of the array is default-initialized;

if T is

std::meta::info

, the object is initialized to the null reflection value;

(since C++26)otherwise, no initialization is performed (see

notes

).

Only (possibly cv-qualified) non-POD class types (or arrays thereof) with automatic storage duration were considered to be default-initialized when no initializer is used. Scalars and POD types with dynamic storage duration were considered to be not initialized (since C++11, this situation was reclassified as a form of default-initialization).

(until C++11)Default-initialization of a const object

If a program calls for the default-initialization of an object of a

const

-qualified type T, T must be a const-default-constructible type.

A type T is const-default-constructible if

Default-initialization of T would invoke a user-provided constructor of T(not inherited from a base class)(since C++11).

T is a class type such that:

each direct non-static data member of T is of class type X (or array thereof), X is const-default-constructible, and

T has no direct

variant members

, and

each

potentially constructed

base class of T is const-default-constructible.

(until C++11)each direct non-variant non-static data member of T has a

default member initializer

or is of const-default-constructible type,

if T is a union with at least one non-static data member, exactly one

variant member

has a default member initializer,

if T is not a union, each anonymous union member is const-default-constructible, and

each

potentially constructed

base class of T is const-default-constructible.

(since C++11)T is an array of const-default-initializable type.

Indeterminate and erroneous values

When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value.

If no initialization is performed for an object, that object retains an indeterminate value until that value is replaced.

(until C++26)When storage for an object with automatic or dynamic storage duration is obtained, the bytes comprising the storage for the object have the following initial value:

If the object has dynamic storage duration, or is the object associated with a variable or

function parameter

whose first declaration is marked with [[

indeterminate

]], the bytes have indeterminate values.

Otherwise, the bytes have erroneous values, where each value is determined by the implementation independently of the state of the program.

If no initialization is performed for an object (including

subobjects

), such a byte retains its initial value until that value is replaced.

If any bit in the

value representation

has an indeterminate value, the object has an indeterminate value.

Otherwise, if any bit in the value representation has an erroneous value, the object has an erroneous value.

(since C++26)If an evaluation produces an indeterminate value, the behavior is

undefined

.

If an evaluation produces an erroneous value, the behavior is

erroneous

.

(since C++26)Special cases

The following types are uninitialized-friendly:

unsignedchar

char, if its underlying type is unsignedchar

Given an indeterminate or erroneous(since C++26) value value, the uninitialized result value of value is:

An indeterminate value, if value is also an indeterminate value.

value, if value is an erroneous value.

(since C++26)If an evaluation produces an indeterminate or erroneous(since C++26) value value of an uninitialized-friendly type, the behavior is well-defined if the evaluation is:

the evaluation of one of the following expressions and operands:

The second or third operand of a

conditional expression

.

The right operand of a

comma expression

.

The operand of an

integral conversion

,

explicit cast

or

static_cast

to an uninitialized-friendly type.

A

discarded-value expression

.

In this case, the result of the operation is the uninitialized result value of value.an evaluation of the right operand of a

simple assignment operator

whose left operand is an lvalue of an uninitialized-friendly type.

In this case, the value of the object referred to by the left operand is replaced by the uninitialized result value of value.the evaluation of the initialization expression when initializing an object of an uninitialized-friendly type.

In this case, that object is initialized to the uninitialized result value of value.Converting an indeterminate value of an uninitialized-friendly type produces an indeterminate value.

Converting an erroneous value of an uninitialized-friendly type produces an erroneous value, the result of the conversion is the value of the converted operand.

(since C++26)// Case 1: Uninitialized objects with dynamic storage duration// All C++ versions: indeterminate value + undefined behaviorintf(boolb){unsignedchar*c=newunsignedchar;unsignedchard=*c;// OK, “d” has an indeterminate valueinte=d;// undefined behaviorreturnb?d:0;// undefined behavior if “b” is true}// Case 2: Uninitialized objects with automatic storage duration// until C++26: indeterminate value + undefined behavior// since C++26: erroneous value + erroneous behaviorintg(boolb){unsignedcharc;// “c” has an indeterminate/erroneous valueunsignedchard=c;// no undefined/erroneous behavior,// but “d” has an indeterminate/erroneous valueassert(c==d);// holds, but both integral promotions have// undefined/erroneous behaviorinte=d;// undefined/erroneous behaviorreturnb?d:0;// undefined/erroneous behavior if “b” is true}// Same as case 2voidh(){intd1,d2;// “d1” and “d2” have indeterminate/erroneous valuesinte1=d1;// undefined/erroneous behaviorinte2=d1;// undefined/erroneous behaviorassert(e1==e2);// holdsassert(e1==d1);// holds, undefined/erroneous behaviorassert(e2==d1);// holds, undefined/erroneous behavior// no undefined/erroneous behavior,// but “d2” has an indeterminate/erroneous valuestd::memcpy(&d2,&d1,sizeof(int));assert(e1==d2);// holds, undefined/erroneous behaviorassert(e2==d2);// holds, undefined/erroneous behavior}Notes

References and const scalar objects cannot be default-initialized.

Feature-test macroValueStdFeature

__cpp_constexpr

201907L

(C++20)Trivial default-initialization and

asm-declaration

in constexpr functions Example

Run this code

#include<string>structT1{intmem;};structT2{intmem;T2(){}// “mem” is not in the initializer list};intn;// static non-class, a two-phase initialization is done:// 1) zero-initialization initializes n to zero// 2) default-initialization does nothing, leaving n being zerointmain(){[[maybe_unused]]intn;// non-class, the value is indeterminatestd::strings;// class, calls default constructor, the value is ""std::stringa[2];// array, default-initializes the elements, the value is {"", ""}// int& r; // Error: a reference// const int n; // Error: a const non-class// const T1 t1; // Error: const class with implicit default constructor[[maybe_unused]]T1t1;// class, calls implicit default constructorconstT2t2;// const class, calls the user-provided default constructor// t2.mem is default-initialized}Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

CWG 178

C++98 there was no value-initialization;
empty initializer invoked default-initialization
(though newT() also performs zero-initialization) empty initializer invokes
value-initialization

CWG 253

C++98 default-initialization of a const object could not
call an implicitly declared default constructor allowed if all subobjects are initialized

CWG 616

C++98 lvalue to rvalue conversion of any
uninitialized object was always UB indeterminate unsignedchar is allowed

CWG 1787

C++98 read from an indeterminate unsignedchar
cached in a register was UB made well-defined

CWG 3089

C++11 std::nullptr_t is not const-default-initializable made const-default-initializable See also

converting constructor

default constructor

explicit

initialization

aggregate initialization

constant initialization

copy-initialization

direct-initialization

list-initialization

reference initialization

value-initialization

zero-initialization

new