Question

Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?

Today I came to know about 3 types of initialization in C++:

  • Zero Initialization
  • Default Initialization
  • Value Initialization

I have googled about it but I found no satisfactory results. All I get is a few standards. What I have understood until now is this: in case of value initialization, a data member can get value equal to zero in some cases.

Please elaborate them (standards) with examples. Also please don't just provide the text from the standard.

Thanks

Was it helpful?

Solution

The types of initialization refer to the language grammar. Here are two examples:

T * p1 = new T;
T * p2 = new T();

The object *p1 is default-initialized, and the object *p2 is value-initialized.

The effect of the initialization depends on the type T: 1) If T is a fundamental, then default-initialization does nothing (i.e. the object is left uninitialized), while value initialization equals zero initialization in that case and means the object is set to zero.

2) If T is an aggregate (i.e. class without constructors or destructor or assignment operator), then each element is recursively default- or value-initialized.

3) If T is of class-type and does have user-defined constructors, then both default- and value-initialization cause a call to the default constructor.

Note that member objects of classes with constructors can in turn be default- or value-initialized:

struct Foo {
    int x;
    int y;
    Foo() : x() { }
};

Now when you say Foo a; then a is default-initialized, so the default constructor is called. This in turn causes a.x to be value-, i.e. zero-initialized, while a.y remains default-, i.e. un-initialized.

(Note that it's not really possible to value-initialize an automatic object, though in C++11, brace-initialization may be used to cause value-initialization, as in Foo a{};. (This behaves exactly the same as Foo a; in our example, consequent to the third paragraph.))

OTHER TIPS

This is dealt with in 8.5 Initializers [dcl.init].


Zero Initialization

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

— if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T. As specified in 4.10, converting an integral constant expression whose value is 0 to a pointer type results in a null pointer value.

— if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;

— if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zeroinitialized and padding is initialized to zero bits;

— if T is an array type, each element is zero-initialized;

— if T is a reference type, no initialization is performed.

Basically, it's equivalent to a memset(&obj, 0, sizeof(objt));, except that it account that the memory representation of a null pointer might not be a 0 value (even though it is represented by a 0 in the language).

// foo.cpp
static char const* p;     // p is zero-initialized
                          // during static initialization

static void init() {
  if (!p) { p = new char[500]; }  // fine as p has been 0-initialized
}

Note: personally I still prefer to use = nullptr to initialize p, just to make the intent clear...


Default Initialization

6/ To default-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

— if T is an array type, each element is default-initialized;

— otherwise, no initialization is performed.

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.

Or basically, a call to the default constructor, accounting for arrays, at least for classes. The last point is a caveat for built-ins (such as int). Those are simply left as is (with garbage inside).

Default initialization is what is called when you defined a variable but do not initialize it explicitly. It is also what happens to attributes of a class that are not listed in the initializer list. So the caveat for built-ins is quite important to a programmer.

int function() {
  int a;         // <-- a is default-initialized (which means nothing happens...)
  return a;      // <-- uses a, so technically undefined behavior
}

struct A { int a; A() {} }; // During the call to A::A(),
                            // A::a is default-initialized (nothing happens...)

The absence of explicit initialization is a left-over from C. It's normally so for optimization reasons but leads to Undefined Behavior if one attempts to use the value...


Value Initialization

7/ To value-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);

— if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.

— if T is an array type, then each element is value-initialized;

— otherwise, the object is zero-initialized.

An object that is value-initialized is deemed to be constructed and thus subject to provisions of this International Standard applying to “constructed” objects, objects “for which the constructor has completed,” etc., even if no constructor is invoked for the object’s initialization.

It is a mix of both the above, meaning that the following syntax:

template <typename T> T value() { return T(); }
                                         ^~~

provides a suitably initialized instance of T whether T is a class type or a built-in type. It's important for templated code to be able to have such a unified syntax.

Note that with C++11, it is also possible to use T{} to achieve the same effect (which helps disambiguates from functions).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top