array initialisation - c++

I'm quite certain that arrays of built in types are unitialized, whereas arrays of UDTs are default initialized.
int foo[5]; // will contain junk
Foo foo[5]; // will contain 5 Foo objects that are default initialized
This occurs regardless of whether the array is allocated on the stack or heap.
However, I'm finding it hard to find an authoritative source on this. Bjarne states that:
"Members of arrays and structures are default initialized or not depending on whether the array or structure is static" which doesn't really tell me too much.
I've also tried to find something in the standard, but so far no to no avail.
Does anyone know of an authoritative source to confirm the above?

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

It says in the C++ standard, in 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 non-static object, the
object and its subobjects, if any,
have an indeterminate initial value.

"Members of arrays and structures are default initialized or not depending on whether the array or structure is static"
This is authoritative, although it could be clearer:
Arrays and structures declared as static are initialized to zeroes.
Local arrays and structures of built-in types (i.e. types that have no constructors) are not initialized.

Related

Dynamically allocated structures are well initialised?

For POD structure, could new Demo_Class[CONST_NUMBER]() guarantee the dynamically allocated structures are well initialised(i.e. not garbage) in C++11 and afterwards?
It would be appreciated that if somebody shed the light on the detailed rules about the initialization the POD structure array.
There are posts about base types, say new int{} and etc. But there is no direct answer about POD structures.
What more, most posts does not mention C++11 and afterwards at all.
UPDATE:
Thanks to eerorika's for the repid answer.
As per the said answer, which says that[emphasise mine]:
To value-initialize an object of type T means:
otherwise, the object is zero-initialized.
How to fully understand that? The struct\class may has many member variables with different types. Does it mean every member variable would be the object is zero-initialized? For example:
struct Point
{
int x;inty;
};
struct Demo
{
Point pt;
double* ptr;
std::string str;
};.
For POD structure, could new Demo_Class[CONST_NUMBER]() guarantee the dynamically allocated structures are well initialised(i.e. not garbage) in C++11 and afterwards?
It has been guaranteed at least since C++03 when value initialisation was introduced (probably also before through older default initialisation rules). The guarantee hasn't been removed in C++11 nor afterwards.
Standard quotes from latest draft:
[dcl.init.general]
If the initializer is (), the object is value-initialized.
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type ([class]), then
if T has either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
otherwise, the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
To zero-initialize an object or reference of type T means:
if T is a scalar type ([basic.types.general]), the object is initialized to the value obtained by converting the integer literal 0 (zero) to T;84
if T is a (possibly cv-qualified) non-union class type, its padding bits ([basic.types.general]) are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;
if T is a (possibly cv-qualified) union type, its padding bits ([basic.types.general]) are initialized to zero bits and the object's first non-static 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.
P.S. Avoid using allocating new. Consider using std::vector instead.

Placement new and uninitialized POD members

Does the C++ standard guarantee that uninitialized POD members retain their previous value after a placement new?
Or more precisely, will the following assert always be satisfied according to C++11?
#include <cstdlib>
#include <cassert>
struct Foo {
int alpha; // NOTE: Uninitialized
int beta = 0;
};
int main()
{
void* p = std::malloc(sizeof (Foo));
int i = some_random_integer();
static_cast<Foo*>(p)->alpha = i;
new (p) Foo;
assert(static_cast<Foo*>(p)->alpha == i);
}
Is the answer the same for C++03?
Does the C++ standard guarantee that uninitialized POD members retain their previous value after a placement new?
Will the following assert always be satisfied according to C++11?
No.
Uninitialized data members have an indeterminate value, and this is not at all the same as saying that the underlying memory is left alone.
[C++11: 5.3.4/15]: A new-expression that creates an object of type T initializes that object as follows:
If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed, the object has indeterminate value.
Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct-initialization.
[C++11: 8.5/6]: To default-initialize an object of type T means:
if T is a (possibly cv-qualified) 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, no initialization is performed.
[C++11: 12.1/6]: A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be
performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement.
[C++11: 12.6.2/8]: In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5;
otherwise, if the entity is a variant member (9.5), no initialization is performed;
otherwise, the entity is default-initialized (8.5).
(NB. the first option in 12.6.2/8 is how your member beta is handled)
[C++11: 8.5/6]: To default-initialize an object of type T means:
if T is a (possibly cv-qualified) 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, no initialization is performed.
[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.
A compiler could choose to zero-out (or otherwise alter) the underlying memory during allocation. For example, Visual Studio in debug mode is known to write recognisable values such as 0xDEADBEEF into memory to aid debugging; in this case, you're likely to see 0xCDCDCDCD which they use to mean "clean memory" (reference).
Will it, in this case? I don't know. I don't think that we can know.
What we do know is that C++ doesn't prohibit it, and I believe that brings us to the conclusion of this answer. :)
Is the answer the same for C++03?
Yes, though through slightly different logic:
[C++03: 5.3.4/15]: A new-expression that creates an object of type T initializes that object as follows:
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;
If the new-initializer is of the form (), the item is value-initialized (8.5);
If the new-initializer is of the form (expression-list) and T is a class type, the appropriate constructor is called, using expression-list as the arguments (8.5);
If the new-initializer is of the form (expression-list) and T is an arithmetic, enumeration, pointer, or pointer-to-member type and expression-list comprises exactly one expression, then the object is initialized to the (possibly converted) value of the expression (8.5);
Otherwise the new-expression is ill-formed.
Now, all that was my strict interpretation of the rules of initialisation.
Speaking practically, I think you're probably correct in seeing a potential conflict with the definition of placement operator new syntax:
[C++11: 18.6.1/3]: Remarks: Intentionally performs no other action.
An example that follows explains that placement new "can be useful for constructing an object at a known address".
However, it doesn't actually talk about the common use of constructing an object at a known address without mungling the values that were already there, but the phrase "performs no other action" does suggest that the intention is that your "indeterminate value" be whatever was in memory previously.
Alternatively, it may simply prohibit the operator itself from taking any action, leaving the allocator free to. It does seem to me that the important point the standard trying to make is that no new memory is allocated.
Regardless, accessing this data invokes undefined behaviour:
[C++11: 4.1/1]: A glvalue (3.10) of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not
an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.
So it doesn't really matter: you couldn't compliantly observe the original value anyway.
C++11 12.6.2/8 "Initializing bases and members" says:
In a non-delegating constructor, if a given non-static data member or
base class is not designated by a mem-initializer-id (including the
case where there is no mem-initializer-list because the constructor
has no ctor-initializer) and the entity is not a virtual base class of
an abstract class (10.4), then
if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in
8.5;
otherwise, if the entity is a variant member (9.5), no initialization is performed;
otherwise, the entity is default-initialized (8.5).
Default initialization on an int does nothing (8.5/6 "Initializers"):
To default-initialize an object of type T means:
if T is a (possibly cv-qualified) 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, no initialization is performed.
So the member alpha should be left alone.

uninitialized const

This compiles perfectly fine with the current MSVC compiler:
struct Foo
{
} const foo;
However, it fails to compile with the current g++ compiler:
error: uninitialized const 'foo' [-fpermissive]
note: 'const struct Foo' has no user-provided default constructor
If I provide a default constructor myself, it works:
struct Foo
{
Foo() {}
} const foo;
Is this another case of MSVC being too permissive, or is g++ too strict here?
The C++03 Standard:
8.5 [dcl.init] paragraph 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.
From the above the error in gcc seems to be perfectly valid.
[2003: 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.
And:
[n3290: 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. [ Note: Objects with static or thread storage
duration are zero-initialized, see 3.6.2._ —end note_ ]
[n3290: 8.5/6]: To default-initialize an object of type T means:
if T is a (possibly cv-qualified) 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, no initialization is performed.
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
So MSVC is more permissive here than both standards mandate.
I don't know the exact wording of the standard, but the error in g++ seems quite more sensible than the option of not saying anything. Consider this:
struct X {
int value;
};
const X constant; // constant.value is undefined
Not in the case of a user provided default constructor (even if it does nothing) the compiler will call that constructor and the object will be initialized (by whatever definition of initialized you have implemented in your constructor).
C++17 Update
C++17 adds some nuance to the requirement that const-qualified class types have a default constructor. The standard now defines the "const-default-constructable" concept:
7 To default-initialize an object of type T means:
(7.1) — If T is a (possibly cv-qualified) class type, constructors are considered. The applicable constructors are enumerated, and the best one for the initializer() is chosen through overload resolution. The constructor thus selected is called, with an empty argument list, to initialize the
object.
(7.2) — If T is an array type, each element is default-initialized.
(7.3) — Otherwise, no initialization is performed.
A class type T is const-default-constructible if default-initialization of T would invoke a user-provided constructor of T (not inherited from a base class) or if
(7.4) — each direct non-variant non-static data member M of T has a default member initializer or, if M is of class type X (or array thereof), X is const-default-constructible,
(7.5) — if T is a union with at least one non-static data member, exactly one variant member has a default member initializer,
(7.6) — if T is not a union, for each anonymous union member with at least one non-static data member (if any), exactly one non-static data member has a default member initializer, and
(7.7) — each potentially constructed base class of T is const-default-constructible.
If a program calls for the default-initialization of an object of a const-qualified type T, T shall be a const-default-constructible class type or array thereof.

Difference between default-initialize and value-initialize in C++03?

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:
Why was the standard changed, i.e. what advantage does this give or what is now possible that wasn't before;
What exacly do the terms "default-initialize" and "value-initialize" represent?
What's the relevant part of the standard?
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.

Stack object creation in C++ - Alternative syntax [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?
I am confused about an issue in C++.
When creating an object on the stack using the default constructor, I thought either one of the following two syntax notations would give the same result:
class MyClass { public: int i; }
int main()
{
MyClass a = MyClass();
MyClass b;
}
However, the first syntax initializes the field to zero, whereas the second one leaves the field uninitialized. So my questions are:
Why is this so? I thought fields in C++ were not supposed to be automatically initialized.
Is there any other differences between the two syntaxes?
Do these syntax variations have separate names to distinguish them from each other?
I’m currently using Microsoft Visual C++ 2010 Express.
Thanks!
In the first, you copy-initialize a from a value-initialized instance of MyClass. From the C++03 standard, §8.5/7:
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
And from §8.5/5:
To value-initialize an object of type T means:
if T is a class type with a user-declared constructor, 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
To zero-initialize an object of type T means:
if T is a scalar type, 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.
In the second, you declare b in a manner that would cause it to be default-initialized if MyClass were not a POD type -- §8.5/5:
To default-initialize an object of type T means:
if T is a non-POD class type, 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.
However, because MyClass is a POD type, b is uninitialized -- §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 non-static 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.
Basically, this is a (relatively) simple WTF in the language, where primitive types will not be initialized by default. The first syntax explicitly initializes them- the second doesn't. User-defined types will always be initialized, so it's only meaningful if you don't initialize it in the constructor, and it will be an error if you don't call the init functions of UDTs that need them.
UDTs that do not do anything insane should not require the first syntax and it's normal to use the second.