14

Cheers and hth. - Alf made a comment in this answer that value initialization is arguably a new feature of C++03 compared to C++98. I wonder what he meant.

Is value initialization part of C++98? Is it present in concept but not in name? Why was it added to the C++03 standard?

I have a copy of the '03 standard but not the '98 standard. Here's the definition of default initialization and value initialization.

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

My guess is that '98 had default initialization but not value initialization and that there's some key difference between the two. To be honest I'm having trouble parsing the standardese here and I don't understand the difference between the definitions.

Community
  • 1
  • 1
Praxeolitic
  • 22,455
  • 16
  • 75
  • 126

1 Answers1

10

Quoting the ISO/IEC 14882:1998 standard document (that was withdrawn from ISO):

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 storage for the object is zero-initialized.

And in paragraph 7:

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

Details on the rationale behind the change can be found in the defect report that made it happen:

This definition is appropriate for local variables, but not for objects that are initialized as a result of executing expressions of the form T(), because the objects yielded by such expressions will be copied immediately, and should therefore have values that are assured of being copyable.
To this end, I propose adding the following new text to 8.5, paragraph 5:

To value-initialize an object of type T means:

  • if T is a class type (clause 9 [class]) 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 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 storage for the object is zero-initialized.

In addition, I propose to change ‘‘default-initialization’’ to ‘‘value-initialization’’ in 5.2.3 paragraph 2.

And, following that, a historical explanation:

Ancient history

Once upon a time, an AT&T compiler developer named Laura Eaves asked me: ‘‘What should be the value of int()?’’ My first thought was that it should be the same value as x has after saying

int x;

but I soon realized that that definition would not do. The reason is that x has an indeterminate value (assuming that it is a local variable), but we don’t mind that x is indeterminate, because we are presumably going to assign a value to x before we use it. In contrast, int() had better not have an indeterminate value, because copying such a value has an undefined effect. It would be silly to forbid a compiler from flagging int() during compilation, only to allow it to flag it during execution! […]

Columbo
  • 60,038
  • 8
  • 155
  • 203
  • You've got it. I propose bringing some of the rationale from the DR into your answer to make it self-contained. Let me know when you've done this so that I can upvote you. :) – Lightness Races in Orbit Dec 08 '14 at 00:51
  • The annoying thing about the C++98 version is that if you have a class containing a `std::string` and some `int` variables, there is no way to have it zero-initialize the ints other than to explicitly list them all in the constructor initializer list. – M.M Dec 08 '14 at 01:39
  • @MattMcNabb I didn't follow. List them all in the initializer list as opposed to doing what? If you don't list them in the initializer list in C++03 are they zero-initialized? – Praxeolitic Dec 08 '14 at 02:19
  • @Praxeolitic in C++98 `T()` doesn't zero-initialize the ints (if T also contains strings), this shows up in many idioms, e.g. `T t = T();` or `T t; t = T();`. For another annoying spot [see here](http://stackoverflow.com/questions/22975262/constructor-to-specify-zero-initialization-of-all-builtin-members) – M.M Dec 08 '14 at 02:27