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