Is this aggregate initialization or default initialization in C++? - c++

Consider following program.
#include <iostream>
int main()
{
int a=int{};
std::cout<<a;
}
Is it uses aggregate initialization or default initialization? I am confused.

Empty parentheses or braces (T() or T{}) perform value initialization. The exception would be the case where the type is an aggregate in which case aggregate initialization would be used. Since int is not an aggregate, it will be value initialized and since it's not a class nor an array, value initialization will do zero-initialization.
You were wondering why it doesn't work in C. Such syntax simply doesn't exist in C, see this answer.

Aggregate initialization is a type of list initialization, which initializes aggregates. An aggregate is an object of type array, or object which has the characteristics defined on this page.
In this case, the type of initialization is most likely value initialization.

Since C++11, by comparison with other SO answers (e.g.: this or this), I would say this is:
a value-initialization (int{}) followed by
a copy-initialization (int a=int{}).
By the way, from C++17, the second step should vanish as int{} is required to directly initialize a.

Related

Does the use of {} in a class member variable std::array result in initializing the array elements? [duplicate]

With C++11 std::array, do I have the guarantee that the syntax std::array<T, N> x; will default-initialize all the elements of the array ?
EDIT: if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
EDIT: on cppreference, the default constructor description says:
(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array
so the answer may be yes. But I would like to be sure of that according to the standard or future standard.
By definition, default initialization is the initialization that occurs when no other initialization is specified; the C++ language guarantees you that any object for which you do not provide an explicit initializer will be default initialized (C++11 §8.5/11). That includes objects of type std::array<T, N> and T[N].
Be aware that there are types for which default initialization has no effect and leaves the object's value indeterminate: any non-class, non-array type (§8.5/6). Consequently, a default-initialized array of objects with such types will have indeterminate value, e.g.:
int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;
Both the c-style array and std::array are filled with integers of indeterminate value, just as plain_int has indeterminate value.
Is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
I'm guessing that when you say "to their default value" you really mean "initialize all elements to T{}". That's not default-initialization, it is value-initialization (8.5/7). You can request value initialization quite easily in C++11 by giving each declaration an empty initializer:
int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};
Which will value-initialize all of the array elements in turn, resulting in plain_int, and all the members of both kinds of arrays, being initialized to zero.
Default-initialization is a term from the Standard potentially meaning no initialization at all, so you probably mean zero-initialization.
The description at cppreference.com is actually a bit misleading. std::array is an aggregate class, and if the element type is primitive, it is POD: "plain old data," with semantics closely matching the C language. The implicitly-defined constructor of std::array< int, N > is a trivial one which does absolutely nothing.
Syntax like std::array< int, 3 >() or std::array< int, 3 > x{} which provide zeroed values do not do so by invoking a constructor. Getting zeroes is part of value-initialization, specified in C++11 §8.5/8:
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized …, and if T has a non-trivial default constructor, the object is default-initialized;
std::array has no user-provided default constructor, so it gets zero-initialized. It has an implicitly-defined default constructor, but it is trivial, so it is never default-initialized. (But this doesn't make a difference since trivial initialization by definition has no effect at runtime.)
if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
C-style arrays and std::array are both aggregates, and the way to completely zero-initialize any aggregate is with the syntax = {}. This works since C++98. Note that C-style arrays cannot have zero extent, and that sizeof (std::array< X, 0 >) is not zero.
Both T x[N]; and std::array<T, N> x; default-initialize every element of the array.
For example, if T = std::string, every element will be an empty string. If T is a class without a default constructor, both will fail to compile. If T = int, every element will have indeterminate value (unless that declaration happens to be at namespace scope)
C++11 std::array::fill is a good option for some cases.
First of all, T x[N] does default initialize the elements, although default initialization of a scalar type T actually does nothing. The above also holds for std::array x. I think what you need is list initialization.

List initialization - What changed in C++14?

These two lines from cppreference
What is the difference between these two statements ? I don't see any difference
until c++14
If the braced-init-list is empty and T is a class type with a default
constructor, value-initialization is performed. Otherwise, if T is an
aggregate type, aggregate initialization is performed.
since c++14
If T is an aggregate type, aggregate initialization is performed.
Otherwise, if the braced-init-list is empty and T is a class type with
a default constructor, value-initialization is performed.
The difference is which one happens when both conditions apply: if T is an aggregate class (as opposed to an array), which certainly has a default constructor, and the braced-init-list is empty. Of course, to understand why that matters, we then have to distinguish value initialization from aggregate initialization from an empty list.
Value initialization zero-initializes the object and then default-initializes it, which for an aggregate is default-initializing each of its members, so the value-initialization is member-wise (plus zeroing padding). Aggregate initialization initializes each member from {}, which is again value initialization for many types but is default initialization for members of class type with a user-provided default constructor. The difference can be seen in
struct A {A() {} int i;};
struct B {A a;}; // aggregate
B b{}; // i is 0 in C++11, uninitialized in C++14
B b2=B(); // i is 0 in both versions
In C++14 only, aggregates can have default member initializers; that can't contribute to a difference in behavior between the two language versions, of course, but it doesn't behave differently between these two rules anyway (since it replaces only the common default initialization).
The difference is the sequence of checking, so the aggregate type checking is taking place at the first place, and only then the rest.

Use of deleted function std::array<T,42>() when T() = delete [duplicate]

With C++11 std::array, do I have the guarantee that the syntax std::array<T, N> x; will default-initialize all the elements of the array ?
EDIT: if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
EDIT: on cppreference, the default constructor description says:
(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array
so the answer may be yes. But I would like to be sure of that according to the standard or future standard.
By definition, default initialization is the initialization that occurs when no other initialization is specified; the C++ language guarantees you that any object for which you do not provide an explicit initializer will be default initialized (C++11 §8.5/11). That includes objects of type std::array<T, N> and T[N].
Be aware that there are types for which default initialization has no effect and leaves the object's value indeterminate: any non-class, non-array type (§8.5/6). Consequently, a default-initialized array of objects with such types will have indeterminate value, e.g.:
int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;
Both the c-style array and std::array are filled with integers of indeterminate value, just as plain_int has indeterminate value.
Is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
I'm guessing that when you say "to their default value" you really mean "initialize all elements to T{}". That's not default-initialization, it is value-initialization (8.5/7). You can request value initialization quite easily in C++11 by giving each declaration an empty initializer:
int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};
Which will value-initialize all of the array elements in turn, resulting in plain_int, and all the members of both kinds of arrays, being initialized to zero.
Default-initialization is a term from the Standard potentially meaning no initialization at all, so you probably mean zero-initialization.
The description at cppreference.com is actually a bit misleading. std::array is an aggregate class, and if the element type is primitive, it is POD: "plain old data," with semantics closely matching the C language. The implicitly-defined constructor of std::array< int, N > is a trivial one which does absolutely nothing.
Syntax like std::array< int, 3 >() or std::array< int, 3 > x{} which provide zeroed values do not do so by invoking a constructor. Getting zeroes is part of value-initialization, specified in C++11 §8.5/8:
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized …, and if T has a non-trivial default constructor, the object is default-initialized;
std::array has no user-provided default constructor, so it gets zero-initialized. It has an implicitly-defined default constructor, but it is trivial, so it is never default-initialized. (But this doesn't make a difference since trivial initialization by definition has no effect at runtime.)
if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
C-style arrays and std::array are both aggregates, and the way to completely zero-initialize any aggregate is with the syntax = {}. This works since C++98. Note that C-style arrays cannot have zero extent, and that sizeof (std::array< X, 0 >) is not zero.
Both T x[N]; and std::array<T, N> x; default-initialize every element of the array.
For example, if T = std::string, every element will be an empty string. If T is a class without a default constructor, both will fail to compile. If T = int, every element will have indeterminate value (unless that declaration happens to be at namespace scope)
C++11 std::array::fill is a good option for some cases.
First of all, T x[N] does default initialize the elements, although default initialization of a scalar type T actually does nothing. The above also holds for std::array x. I think what you need is list initialization.

Zero-Initialize array member in initialization list

I have a class with an array member that I would like to initialize to all zeros.
class X
{
private:
int m_array[10];
};
For a local variable, there is a straightforward way to zero-initialize (see here):
int myArray[10] = {};
Also, the class member m_array clearly needs to be initialized, as default-initializing ints will just leave random garbage, as explained here.
However, I can see two ways of doing this for a member array:
With parentheses:
public:
X()
: m_array()
{}
With braces:
public:
X()
: m_array{}
{}
Are both correct? Is there any difference between the two in C++11?
Initialising any member with () performs value initialisation.
Initialising any class type with a default constructor with {} performs value initialisation.
Initialising any other aggregate type (including arrays) with {} performs list initialisation, and is equivalent to initialising each of the aggregate's members with {}.
Initialising any reference type with {} constructs a temporary object, which is initialised from {}, and binds the reference to that temporary.
Initialising any other type with {} performs value initialisation.
Therefore, for pretty much all types, initialisation from {} will give the same result as value initialisation. You cannot have arrays of references, so those cannot be an exception. You might be able to construct arrays of aggregate class types without a default constructor, but compilers are not in agreement on the exact rules. But to get back to your question, all these corner cases do not really matter for you: for your specific array element type, they have the exact same effect.
The types of initialization can be kind of tedious to go through, but in this case it is trivial. For:
public:
X()
: m_array()
{}
since the expression-list between the parentheses are empty, value-initialization occurs. Similarly for:
public:
X()
: m_array{}
{}
list-initialization occurs, and subsequently value-initialization since the brace-init-list is empty.
To give a more comprehensive answer, let's go through §8.5 of N4140.
If no initializer is specified for an object, the object is
default-initialized. When storage for an object with automatic or
dynamic storage duration is obtained, the object has an indeterminate
value, and if no initialization is performed for the object, that
object retains an indeterminate value until that value is replaced
(5.17).
This indeterminate value is what you refer to as garbage values.
To zero-initialize an object or reference of type T means:
— if T is an array type, each element is zero-initialized
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type ... then the object is default-initialized; ...
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized.
The semantics of initializers are as follows. ...
— If the initializer is a (non-parenthesized) braced-init-list, the object or reference is list-initialized (8.5.4).
— If the initializer is (), the object is value-initialized.
So far it's clear that value initialization will make each element of the array zero since int is not a class type. But we have not yet covered list initialization and aggregate initialization, since an array is an aggregate.
§8.5.4:
List-initialization of an object or reference of type T is defined as follows:
— If T is an aggregate, aggregate initialization is performed (8.5.1).
And back to §8.5.1:
If there are fewer initializer-clauses in the list than there
are members in the aggregate, then each member not explicitly
initialized shall be initialized from its brace-or-equal-initializer
or, if there is no brace-or-equal-initializer, from an empty
initializer list (8.5.4).
And we end with §8.5.4 again:
List-initialization of an object or reference of type T is defined as follows:
— Otherwise, if the initializer list has no elements, the object is value-initialized.
Since traversing the (draft) standard can take breath out of you, I recommend cppreference as it breaks it down pretty good.
Relevant links:
cppreference:
aggregate initialization
value initialization
Draft standard:
N4140
Parentheses work in C++98, and are calling for zero initialization, which is what you want. I verified on gcc 4.3. Edit: removed incorrect statement about C++11. I also confirmed that empty braces perform empty-list-initialization using clang 3.4 with -std=c++11.

Default initialization of std::array?

With C++11 std::array, do I have the guarantee that the syntax std::array<T, N> x; will default-initialize all the elements of the array ?
EDIT: if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
EDIT: on cppreference, the default constructor description says:
(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array
so the answer may be yes. But I would like to be sure of that according to the standard or future standard.
By definition, default initialization is the initialization that occurs when no other initialization is specified; the C++ language guarantees you that any object for which you do not provide an explicit initializer will be default initialized (C++11 §8.5/11). That includes objects of type std::array<T, N> and T[N].
Be aware that there are types for which default initialization has no effect and leaves the object's value indeterminate: any non-class, non-array type (§8.5/6). Consequently, a default-initialized array of objects with such types will have indeterminate value, e.g.:
int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;
Both the c-style array and std::array are filled with integers of indeterminate value, just as plain_int has indeterminate value.
Is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
I'm guessing that when you say "to their default value" you really mean "initialize all elements to T{}". That's not default-initialization, it is value-initialization (8.5/7). You can request value initialization quite easily in C++11 by giving each declaration an empty initializer:
int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};
Which will value-initialize all of the array elements in turn, resulting in plain_int, and all the members of both kinds of arrays, being initialized to zero.
Default-initialization is a term from the Standard potentially meaning no initialization at all, so you probably mean zero-initialization.
The description at cppreference.com is actually a bit misleading. std::array is an aggregate class, and if the element type is primitive, it is POD: "plain old data," with semantics closely matching the C language. The implicitly-defined constructor of std::array< int, N > is a trivial one which does absolutely nothing.
Syntax like std::array< int, 3 >() or std::array< int, 3 > x{} which provide zeroed values do not do so by invoking a constructor. Getting zeroes is part of value-initialization, specified in C++11 §8.5/8:
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized …, and if T has a non-trivial default constructor, the object is default-initialized;
std::array has no user-provided default constructor, so it gets zero-initialized. It has an implicitly-defined default constructor, but it is trivial, so it is never default-initialized. (But this doesn't make a difference since trivial initialization by definition has no effect at runtime.)
if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?
C-style arrays and std::array are both aggregates, and the way to completely zero-initialize any aggregate is with the syntax = {}. This works since C++98. Note that C-style arrays cannot have zero extent, and that sizeof (std::array< X, 0 >) is not zero.
Both T x[N]; and std::array<T, N> x; default-initialize every element of the array.
For example, if T = std::string, every element will be an empty string. If T is a class without a default constructor, both will fail to compile. If T = int, every element will have indeterminate value (unless that declaration happens to be at namespace scope)
C++11 std::array::fill is a good option for some cases.
First of all, T x[N] does default initialize the elements, although default initialization of a scalar type T actually does nothing. The above also holds for std::array x. I think what you need is list initialization.