aggregate initialization
aggregate initialization
Initializes an aggregate from braced-init-list.
Syntax
T object = {arg1, arg2, ...}; | (1) | |
---|---|---|
T object {arg1, arg2, ...}; | (2) | (since C++11) |
Explanation
Aggregate initialization is a form of list-initialization, which initializes aggregates
.
An aggregate is one of the following types:
- array type
no default member initializers | (since C++11)(until C++14) |
---|
- no default member initializers
(since C++11)
(until C++14)
The effects of aggregate initialization are:
- Each direct public base, (since C++17) array element, or non-static class member, in order of array subscript/appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list.
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized. If a member of a reference type is one of these remaining members, the program is ill-formed. | (until C++11) |
---|---|
If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed. | (since C++11) |
- If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized. If a member of a reference type is one of these remaining members, the program is ill-formed.
(until C++11)
- If the number of initializer clauses is less than the number of members and bases (since C++17) or initializer list is completely empty, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
(since C++11)
- If the aggregate initialization uses the form with the equal sign (
T a = {args..}
), (until C++14) the braces around the nested initializer lists may be elided (omitted), in which case as many initializer clauses as necessary are used to initialize every member or element of the corresponding subaggregate, and the subsequent initializer clauses are used to initialize the following members of the object. However, if the object has a sub-aggregate without any members (an empty struct, or a struct holding only static members), brace elision is not allowed, and an empty nested list{}
must be used.
Character arrays
Arrays of char
acter types (char
, signed char
, unsigned char
, char16_t
, char32_t
, wchar_t
) can be initialized from an appropriate string literal, optionally enclosed in braces. Successive char
acters of the string literal (which includes the implicit terminating null char
acter) initialize the elements of the array. If the size of the array is specified and it is larger than the number of char
acters in the string literal, the remaining char
acters are zero-initialized.
char a[] = "abc";
// equivalent to char a[4] = {'a', 'b', 'c', '\0'};
// unsigned char b[3] = "abc"; // Error: initializer string too long
unsigned char b[5]{"abc"};
// equivalent to unsigned char b[5] = {'a', 'b', 'c', '\0', '\0'};
wchar_t c[] = {L"кошка"}; // optional braces
// equivalent to wchar_t c[6] = {L'к', L'о', L'ш', L'к', L'а', L'\0'};
Notes
An aggregate class or array may include non-aggregate public bases (since C++17), members, or elements, which are initialized as described above (e.g. copy-initialization from the corresponding initializer clause).
Until C++11, narrowing conversions were permitted in aggregate initialization, but they are no longer allowed.
Until C++11, aggregate initialization could not be used in a constructor initializer list due to syntax restrictions.
Until C++14, the direct-initialization form T a {args..}
did not permit brace elision.
In C, character array of size one less than the size of the string literal may be initialized from a string literal; the resulting array is not null-terminated. This is not allowed in C++.
Example
#include <string>
#include <array>
struct S {
int x;
struct Foo {
int i;
int j;
int a[3];
} b;
};
union U {
int a;
const char* b;
};
int main()
{
S s1 = { 1, { 2, 3, {4, 5, 6} } };
S s2 = { 1, 2, 3, 4, 5, 6}; // same, but with brace elision
S s3{1, {2, 3, {4, 5, 6} } }; // same, using direct-list-initialization syntax
S s4{1, 2, 3, 4, 5, 6}; // error in C++11: brace-elision only allowed with equals sign
// okay in C++14
int ar[] = {1,2,3}; // ar is int[3]
// char cr[3] = {'a', 'b', 'c', 'd'}; // too many initializer clauses
char cr[3] = {'a'}; // array initialized as {'a', '\0', '\0'}
int ar2d1[2][2] = {{1, 2}, {3, 4}}; // fully-braced 2D array: {1, 2}
// {3, 4}
int ar2d2[2][2] = {1, 2, 3, 4}; // brace elision: {1, 2}
// {3, 4}
int ar2d3[2][2] = {{1}, {2}}; // only first column: {1, 0}
// {2, 0}
std::array<int, 3> std_ar2{ {1,2,3} }; // std::array is an aggregate
std::array<int, 3> std_ar1 = {1, 2, 3}; // brace-elision okay
int ai[] = { 1, 2.0 }; // narrowing conversion from double to int:
// error in C++11, okay in C++03
std::string ars[] = {std::string("one"), // copy-initialization
"two", // conversion, then copy-initialization
{'t', 'h', 'r', 'e', 'e'} }; // list-initialization
U u1 = {1}; // OK, first member of the union
// U u2 = { 0, "asdf" }; // error: too many initializers for union
// U u3 = { "asdf" }; // error: invalid conversion to int
}
// aggregate
struct base1 { int b1, b2 = 42; };
// non-aggregate
struct base2 {
base2() : b3(42) {}
int b3;
};
// aggregate in C++17
struct derived : base1, base2 { int d; };
derived d1{ {1, 2}, { }, 4}; // d1.b1 = 1, d1.b2 = 2, d1.b3 = 42, d1.d = 4
derived d2{ { }, { }, 4}; // d2.b1 = 0, d2.b2 = 42, d2.b3 = 42, d2.d = 4
See also
- list initialization
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
http://en.cppreference.com/w/cpp/language/aggregate_initialization