36

C++2003 8.5/5 says:

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.

[Emphasis added.]

The C++2011 standard changed that last item to

— otherwise, no initialization is performed.

This seems like it would be a breaking change for some programs. Was this intentional?

Edit

Here's some code to motivate this question:

class Foo {
  public:
    Foo() : m_values() {}

    int m_values[3];
};

Before C++11, I thought the explicit mention of m_values in the default constructor would default-initialize that array. And since the elements of the array are scalar, I expected that to mean the values were all set to 0.

In C++11, it seems there's no longer a guarantee that this will happen. But maybe, as Mooing Duck pointed out in the comments, perhaps this is no longer a case of default initialization but some other form which preserves the expected behavior. Citations welcome.

sbi
  • 219,715
  • 46
  • 258
  • 445
Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • the objects are not initialized. so, they are UNINITIALIZED OBJECTS. – Victor Mar 06 '14 at 18:42
  • 1
    @Victor: He's aware. His point is that the change from initialized to uninitialized is a breaking change. – Mooing Duck Mar 06 '14 at 18:47
  • 3
    I recall hearing that C++03 didn't have "value-initialization" vs "default initialization" vs "zero initialization" or something. Is it possible that things that were previously default initialized are now zero initialized, which makes this into a not-breaking change? – Mooing Duck Mar 06 '14 at 18:48
  • 2
    `m_values` should be value-initialized because it is part of the member initializer list with empty parentheses. –  Mar 06 '14 at 19:32

3 Answers3

25

The final effects are almost the same. In C++03, the use of default-initialize was restricted to non-POD class type, so the last point never applied. In C++11, the standard simplifies the wording by eliminating the condition with regards to where default-initialization was used, and changes the definition of default-initialization to cover all of the cases in a way to correspond what happened before.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Specifically, C++03 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 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. – Casey Mar 06 '14 at 20:11
  • vs. C++11 8.5/11: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. – Casey Mar 06 '14 at 20:12
  • 2
    I don't quite I understand this answer. Are you saying that since the `m_values` array in the example is POD that default-initialize never applied, not even in C++03? Can you clarify? If I construct a `Foo` as shown above, will the values in `m_values` be 0 or indeterminate? – Adrian McCarthy Mar 07 '14 at 00:46
  • 2
    @JamesKanze: Your answer looks helpful to many, but I still have the questions from me previous comment. If you could clear those up, I'd happily accept it. – Adrian McCarthy Mar 19 '14 at 17:23
  • @AdrianMcCarthy: Because of the explicit `m_values()` in the contructor, the array is never default initialized in any version of C++; it is value initialized (which is the same in C++03 and 11). If that was not present, the array be be uninitialized in C++03 and default initialized in C++11. – Chris Dodd Aug 15 '17 at 17:43
3

According to cppreference.com (because it uses friendlier language than the standard):

Default initialization is performed in three situations:

3) when a base class or a non-static data member is not mentioned in a constructor initializer list and that constructor is called.

Value initialization is performed in three situations:

3,7) when a non-static data member or a base class is initialized using a member initializer with an empty pair of parentheses or braces (since C++11)

Note that the C++11 part belongs with the or braces, not with the entire paragraph.

And:

To value-initialize an object of type T means:
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized

So in C++11 default-initialization does not zero-initialize members but value-initialization does.

2

Strictly speaking, the definition of default-initialize has changed from C++03 to C++11. But one has also to take into account that the situations when an object is _default-initialize_d changed:

§8.5p9 C++03 states:

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.

§8.5p11 C++11 states:

If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value.

As @JamesKanze already pointed out, default-initialization is performed in C++03 when no initializer for an object of non-POD class type is specified. In C++11 an object (of arbitrary type) is default-initialized if no initializer is specified. Because of this change, the definition of default-initialize had also to be changed in order to be compatible with C++03.


Your example has nothing to do with default-initialization. It has been always the case that an object whose initializer is an empty set of parentheses is value-initialized.

MWid
  • 4,429
  • 3
  • 20
  • 20