views:

500

answers:

4

While trying to answer this question I found that the code int* p = new int[10](); compiles fine with VC9 compiler and initializes the integers to 0. So my questions are:

  1. First of all is this valid C++ or is it a microsoft extension?
  2. Is it guaranteed to initialize all the elements of the array?
  3. Also, is there any difference if I do new int; or new int();? Does the latter guarantee to initialize the variable?
A: 

If I may guesstimate a bit (I'm sure I'll be corrected if I'm wrong):

The latter () does value-initialization (as it's called in standardese) which makes the integer have value 0 in this case.

That is a rather new addition to the standard (C++03?) so older compilers may not support it, and leave it uniintialized.

I recall getting a lot of warnings w.r.t this when switching from MSVS 2003 to 2005 (I think), where the compiler said that "this member will be zero-initialized now, it wasn't before".

Marcus Lindblom
There is no such thing as a C++03 standard, though it is true that MSVS has become more standards-compliant with each version.
Gorpik
@Gorpik, the current standard is ISO/IEC 14882:2003, and if you use the common rule of naming standards by the year it would be c++03, even if that is not the proper name (as the next standard will surely not be called c++11 even if most people will refer to it as such)
David Rodríguez - dribeas
Sorry, you are right. I had forgotten the standard amendment published in 2003.
Gorpik
+2  A: 

From the standard. "To default-initialize an object of type T means: -- if T is a non-POD class type [the case like vector], the default constructor for T is called."

The constructor notation T() is used to express the default value of type T and that this is zero for built in types and the default constructor for user-defined types. The construct POD() produces value initialisation and according to the stdandard, which results in all members and sub members being either default constructed or zero initialised.

This is why your statement is legal, but is it zero initialized as per the standard; needs some detailed lookup IMHO.

BUT, i could not find in the standard where the it defines the meaning of default construction for built in types.

EDIT:-

struct S { int x; };

void f () {
   S s1;       // s1.x is uninitialized here
   S s2 = S(); // s2.x is zero here
}

I think we often make up our own interpretation of what default construction applied to built in types means; because the C++ standard doesn't define it (atleast i could not find it) and i remember Stroustrup or Josuttis say that it means T() which is described as being value initialisation is "zero converted to type T" for built in types.

Since int* is a built-in type it is initialized to zero.

But i am really not sure.

Abhay
Is that really an initializer list? I thought those where { 1,2,3 } ?
Marcus Lindblom
@Abhay: §8.5 is not relevant to the question. As Marcus Lindblom correctly points out, initializer lists are of the form `{ 1,2,3 }` and cannot be used (in the current standard) with `new` expressions. The rules for initilization in new expressions fall under §5.3.4 [expr.new]
David Rodríguez - dribeas
@dribeas: Yes u r right, edited the post, but i ventured into it in context of the OPs allocating arrays to pick up the initialization part. My bad :-(
Abhay
On the edit: the standard has a complete definition for all intialization rules, even if they are quite complex and hard to follow. §8.5/9 states that if no initializer is specified for a non-static POD object it will have indeterminate initial value (I believe that is what you refer to as 'default construct', that is different to default initialize). §8.5/7 states that an initializer that is an empty set of parenthesis means *value-initialize*.
David Rodríguez - dribeas
BTW, *default-initialize* for POD types means *zero-initialize* for POD types, even if that is not what happens in `int x;`
David Rodríguez - dribeas
@dribeas: O.K. So §8.5/6 should read 'default value initialize' instead of 'default construct'. Am i right? BTW, n3000 version of the draft seems to have corrected it.
Abhay
@Abhay: §8.5/6 reads 'Every object of static storage duration shall be zero-initialized at program startup before any other initialization takes place.', there is no 'default value initialize' there. What version of the standard are you looking at? (the quote is from INCITS ISO IEC 14882:2003, which is the current standard)
David Rodríguez - dribeas
@dribeas: Sorry was away in a meeting, In my copy of the standard (my employer's), 8.5.6 says "To default-initialize an object of type T means" and I noticed in the n3000 version they have erased 'default-constructed' and replaced it with 'default initialized' for array types.
Abhay
@David, As far as i know, C++03 does not know the term "initializer list". It knows the term "initializer-list" which is a "1, 2, 3" (so a function call argument list is an initializer-list, as well as the argument list in a functional cast or new expression). And in C++0x an "initializer list" is a "{ 1, 2, 3 }" (but in C++03 this is never formally defined, and just used informally, like in "the empty initializer list {} ...") and finally there is an "initializer_list" in C++0x too which is `std::initializer_list`. Quite a bit like in a jungle!
Johannes Schaub - litb
@Johanes Schaub: Make it a '*brace enclosed* initializer-list' for precision, in C++03 §12.6.1/2
David Rodríguez - dribeas
@David, ah that makes sense. I do like C++0x' new way of using it in `new`, but i dislike it the same way that it can't deduce the number of arguments from the list. `new int[]{1, 2}` won't work. One has to say `new int[2]{1, 2}` i think that sucks.
Johannes Schaub - litb
+13  A: 

First of all is this valid C++ or is it a microsoft extension?

It is valid in C++, the relevant part of the standard is 5.3.4, with the first paragraph containing the grammar

Is it guaranteed to initialize all the elements of the array?

Yes. Paragraph 5.3.4/15 states that

A new-expression that creates an object of type T initializes that object as follows:

...

  • If the new-initializer is of the form (), the item is value-initialized (8.5)

where value initialized for POD means zero-initialize.

Also, is there any difference if I do new int; or new int();? Does the latter guarantee to initialize the variable?

Yes they are different. According with the quote above new int() will zero-initialize the integer. In a previous block of the same paragraph:

If the new-initializer is omitted:

  • If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized (8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.

  • Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;

so new int will not initialize the memory.

David Rodríguez - dribeas
+1  A: 
  1. This is valid C++ according to paragraph 5.3.4/1, which is hard to quote here due to special formatting.

  2. According to 5.3.4/15 the item is value-initialized if form () is used, see paragraph 8.5 but the short answer is yes.

  3. Yes there is a difference in the first case the variable is not value-initalized and can be anything, in the second case it's value initialized and will be zero.

Andreas Brinck