8

I had always thought that creating a new object would always call the default constructor on an object, and whether the constructor was explicit or automatically generated by the compiler made no difference. According to this highly regarded answer to a different question, this changed in a subtle way between C++98 and C++03 and now works like so:

struct B { ~B(); int m; }; // non-POD, compiler generated default ctor 
new B;   // default-initializes (leaves B::m uninitialized)
new B(); // value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.

Can anyone tell me:

  1. Why was the standard changed, i.e. what advantage does this give or what is now possible that wasn't before;
  2. What exacly do the terms "default-initialize" and "value-initialize" represent?
  3. What's the relevant part of the standard?
Community
  • 1
  • 1
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • The relevant part of the new C++11 standard is 8.5 ("Initializers") clauses 5,6,7. – Kerrek SB Aug 16 '11 at 20:53
  • Maybe it gives people the option of using the default ctor or not. In the old version of C++ the brackets were normally missed off when there were no parameters. So having the brackets on the new option will affect less legacy code. – QuentinUK Aug 16 '11 at 21:21
  • I would not call it change, but rather correction. It at least makes sense in the context of e.g. std::map where the values created by [] are value intialized, so for e.g. std::map all U* are initlaized to 0 – PlasmaHH Aug 16 '11 at 21:45
  • @PlasmaHH, I think I'm getting a light bulb moment - are you saying that prior to C++03, POD types would **not** get initialized even if constructed with `()`? I'm sure in the particular `std::map` case that `std::pair()` could explicitly call the constructors for `A` and `B`. – Mark Ransom Aug 16 '11 at 21:55
  • @Mark Ransom: http://www.acceleratedcpp.com/authors/koenig/c++std/revisions.pdf contains an inofficial list of differences between 98 and 03. In changes around 8.5 the key difference is that for non-pods with no user defined ctor, the subobjects were previously not initialized because () was default initialization, which called the default ctor, which did nothing. Now () is value initialization, which when there is no user defined ctor will value-init all subobjects. Since pair is no POD it would always call A() and B() when default initd, so the key here is when B() is non-POD with no user de – PlasmaHH Aug 17 '11 at 09:31

1 Answers1

3

I do not know what the rationales around the change (or how the standard was before), but on how it is, basically default-initialization is either calling a user defined constructor or doing nothing (lots of hand-waving here: this is recursively applied to each subobject, which means that the subobjects with a default constructor will be initialized, the subobjects with no user defined constructors will be left uninitialized).

This falls within the only pay for what you want philosophy of the language and is compatible with C in all the types that are C compatible. On the other hand, you can request value-initialization, and that is the equivalent to calling the default constructor for objects that have it or initializing to 0 converted to the appropriate type for the rest of the subobjects.

This is described in §8.5 Initializers, and it is not trivial to navigate through. The definitions for zero-initialize, default-initialize and value-initialize are the 5th paragraph:

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 zeroinitialized;

— if T is a union type, the object’s first named data member89) 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

A program that calls for default-initialization or value-initialization of an entity of reference type is illformed. If T is a cv-qualified type, the cv-unqualified version of T is used for these definitions of zeroinitialization, default-initialization, and value-initialization.

Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • Your leading paragraph has defines the behavior of Default-initialization as either using the ctor or its left uninitialized. My question is the interpretation of the included quotation of the 8.5 Initializer section defining the default-initialize which has as the final step ..."-otherwise, the object is zero-initialized". Its seems to suggest that if there is no ctor then use the rules of zero-initialize vs leaving it uninitialized. – TheChrisONeil Nov 04 '13 at 21:45
  • @CBO: That particular quote is from C++03, in C++11 the last item has changed and reads: *otherwise, no initialization is performed*. The key at this point is what is written a few paragraphs later. For an object with no initializer provided, in C++03 the object is left uninitialized (in /9), in C++11 the object is *default-initialized* (/12). Not sure if this answers your concern – David Rodríguez - dribeas Nov 04 '13 at 21:59
  • Makes sense and thanks for following up. I would recommend updating your post to now include the content of C++11. – TheChrisONeil Nov 05 '13 at 13:36