Question

I'm quite certain that arrays of built in types are unitialized, whereas arrays of UDTs are default initialized.

int foo[5]; // will contain junk
Foo foo[5]; // will contain 5 Foo objects that are default initialized

This occurs regardless of whether the array is allocated on the stack or heap.

However, I'm finding it hard to find an authoritative source on this. Bjarne states that:

"Members of arrays and structures are default initialized or not depending on whether the array or structure is static" which doesn't really tell me too much.

I've also tried to find something in the standard, but so far no to no avail.

Does anyone know of an authoritative source to confirm the above?

Was it helpful?

Solution

ISO C++03 is about as authoritative as it gets:

A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor. Similarly, a POD-union is an aggregate union that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor. A POD class is a class that is either a POD-struct or a POD-union.

Arithmetic types (3.9.1), enumeration types, pointer types, and pointer to member types (3.9.2), and cv-qualified versions of these types (3.9.3) are collectively called scalar types. Scalar types, POD-struct types, POD-union types (clause 9), arrays of such types and cv-qualified versions of these types (3.9.3) are collectively called POD types.

To zero-initialize an object of type T means:

  • if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
  • if T is a non-union class type, each nonstatic data member and each base-class subobject is zero-initialized;
  • if T is a union type, the object’s first 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.

To default-initialize an object of type T means:

  • if T is a non-POD 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, the object is zero-initialized.

To value-initialize an object of type T means:

  • if T is a class type (clause 9) with a user-declared 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 non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
  • if T is an array type, then each element is value-initialized;
  • otherwise, the object is zero-initialized

Every object of static storage duration shall be zero-initialized at program startup before any other initialization takes place. [Note: in some cases, additional initialization is done later.]

An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value); if the object or any of its subobjects are of const-qualified type, the program is ill-formed.

For your example, int is definitely a POD type (it's an arithmetic type), and therefore a local or field of type int, in the absence of initializer, will have an indeterminate value. For Foo, this depends on how it is defined - roughly speaking, if it doesn't have a constructor, and all its members are of POD types, then it is itself a POD type, and no initialization takes place either. Otherwise, the default constructor is called. Even then, this doesn't mean that members are initialized - rules are recursive, so POD members of non-POD type won't be initialized unless the constructor of that type specifically does that (in its initializer list).

Static variables and fields will in all cases be zero-initialized. Note that this applies to non-PODs too - meaning that a static variable of a class type is guaranteed to have all fields recursively set to (T)0 even before its constructor runs.

A handy trick to default-initialize any aggregate POD type is to use {} in initializer - note that it works with structs as well as arrays:

char s[10] = {}; // all elements default-initialized
Foo foo = {};    // all fields recursively default-initialized

OTHER TIPS

It says in the C++ standard, in 8.5.9:

If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a non-static object, the object and its subobjects, if any, have an indeterminate initial value.

"Members of arrays and structures are default initialized or not depending on whether the array or structure is static"

This is authoritative, although it could be clearer:

  • Arrays and structures declared as static are initialized to zeroes.
  • Local arrays and structures of built-in types (i.e. types that have no constructors) are not initialized.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top