General topics | ||||||||||||||||||||||||||
Flow control | ||||||||||||||||||||||||||
Conditional execution statements | ||||||||||||||||||||||||||
Iteration statements (loops) | ||||||||||||||||||||||||||
Jump statements | ||||||||||||||||||||||||||
Functions | ||||||||||||||||||||||||||
Function declaration | ||||||||||||||||||||||||||
Lambda function expression | ||||||||||||||||||||||||||
inline specifier | ||||||||||||||||||||||||||
Dynamic exception specifications(until C++17*) | ||||||||||||||||||||||||||
noexcept specifier(C++11) | ||||||||||||||||||||||||||
Exceptions | ||||||||||||||||||||||||||
Namespaces | ||||||||||||||||||||||||||
Types | ||||||||||||||||||||||||||
Specifiers | ||||||||||||||||||||||||||
| ||||||||||||||||||||||||||
Storage duration specifiers | ||||||||||||||||||||||||||
Initialization | ||||||||||||||||||||||||||
|
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
Initializes an aggregate from an initializer list. It is a form oflist-initialization(since C++11).
Contents |
T object = { arg1, arg2, ...}; | (1) | ||||||||
T object{ arg1, arg2, ...}; | (2) | (since C++11) | |||||||
T object = { . des1 = arg1, . des2{ arg2} ...}; | (3) | (since C++20) | |||||||
T object{ . des1 = arg1, . des2{ arg2} ...}; | (4) | (since C++20) | |||||||
Anaggregate is one of the following types:
| (until C++11) |
| (since C++11) (until C++20) |
| (since C++20) |
(until C++17) | |
| (since C++17) |
(since C++11) (until C++14) |
Theelements of an aggregate are:
| (until C++17) |
| (since C++17) |
Eachinitializer clause in a brace-enclosed initializer list is said toappertain to an element of the aggregate being initialized or to an element of one of its subaggregates.
Considering the sequence of initializer clauses, and the sequence of aggregate elements initially formed as the sequence of elements of the aggregate being initialized and potentially modified as described below:
The analysis is complete when all initializer clauses have been exhausted. If any initializer clause remains that does not appertain to an element of the aggregate or one of its subaggregates, the program is ill-formed.
struct S1{long a, b;};struct S2{ S1 s, t;}; // Each subaggregate of “x” is appertained to an initializer clause starting with {S2 x[2]={// appertains to “x[0]”{{1L,2L},// appertains to “x[0].s”{3L,4L}// appertains to “x[0].t”},// appertains to “x[1]”{{5L,6L},// appertains to “x[1].s”{7L,8L}// appertains to “x[1].t”}}; // “x” and “y” have the same value (see below)S2 y[2]={1L,2L,3L,4L,5L,6L,7L,8L}; // The process of the appertainment analysis of “y”:// 1. Initializes the aggregate element sequence (x[0], x[1]) and// the initializer clause sequence (1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L).// 2. Starting from the first elements of each sequence,// checks whether 1L appertains to x[0]:// · x[0] is an aggregate.// · 1L does not begin with {.// · 1L is an expression, but it cannot be implicitly converted to S2.// · x[0] has aggregate elements.// 3. 1L cannot appertain to x[0], therefore x[0] is replaced by x[0].s and x[0].t,// the aggregate element sequence becomes (x[0].s, x[0].t, x[1]).// 4. Resumes the appertainment check, but 1L cannot appertain to x[0].s either.// 5. The aggregate element sequence now becomes (x[0].s.a, x[0].s.b, x[0].t, x[1]).// 6. Resumes the appertainment check again:// 1L appertains to x[0].s.a, and 2L appertains to x[0].s.b.// 7. The rest of the appertainment analysis works similarly. char cv[4]={'a','s','d','f',0};// Error: too many initializer clauses
The effects of aggregate initialization are:
| (since C++20) |
union u{int a;constchar* b;}; u a={1};// OK: explicitly initializes member `a`u b={0,"asdf"};// error: explicitly initializes two membersu c={"asdf"};// error: int cannot be initialized by "asdf" // C++20 designated initializer listsu d={.b="asdf"};// OK: can explicitly initialize a non-initial memberu e={.a=1, .b="asdf"};// error: explicitly initializes two members
For each explicitly initialized element:
struct C{union{int a;constchar* p;}; int x;} c={.a=1, .x=3};// initializes c.a with 1 and c.x with 3
| (since C++20) |
| (until C++20) |
| (since C++20) |
struct A{int x; struct B{int i;int j;} b;} a={1,{2,3}};// initializes a.x with 1, a.b.i with 2, a.b.j with 3 struct base1{int b1, b2=42;}; struct base2{ base2(){ b3=42;} int b3;}; struct derived: base1, base2{int d;}; derived d1{{1,2},{},4};// initializes d1.b1 with 1, d1.b2 with 2,// d1.b3 with 42, d1.d with 4derived d2{{},{},4};// initializes d2.b1 with 0, d2.b2 with 42,// d2.b3 with 42, d2.d with 4
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
| (since C++11) |
struct S{int a;constchar* b;int c;int d= b[a];}; // initializes ss.a with 1,// ss.b with "asdf",// ss.c with the value of an expression of the form int{} (that is, 0),// and ss.d with the value of ss.b[ss.a] (that is, 's')S ss={1,"asdf"};
If the aggregate is a union and the initializer list is empty, then
| (since C++11) |
The number of elements in an array of unknown bound initialized with a brace-enclosed initializer list is the number of explicitly initialized elements of the array. An array of unknown bound cannot be initialized with{}.
int x[]={1,3,5};// x has 3 elements struct Y{int i, j, k;}; Y y[]={1,2,3,4,5,6};// y has only 2 elements:// 1, 2 and 3 appertain to y[0],// 4, 5 and 6 appertain to y[1] int z[]={}// Error: cannot declare an array without any element
Designated initializersThe syntax forms(3,4) are known as designated initializers: eachdesignator must name a direct non-static data member of T, and alldesignator s used in the expression must appear in the same order as the data members of T. struct A{int x;int y;int z;}; A a{.x=1, .y=2, .z=3};// okA b{.y=2, .z=3, .x=1};// error; designator order does not match declaration order Each direct non-static data member named by the designated initializer is initialized from the corresponding brace-or-equals initializer that follows the designator. Narrowing conversions are prohibited. Designated initializer can be used to initialize aunion into the state other than the first. Only one initializer may be provided for a union. union u{int a;constchar* b;}; u f={.b="asdf"};// OK, active member of the union is bu g={.a=1, .b="asdf"};// Error, only one initializer may be provided For a non-union aggregate, elements for which a designated initializer is not provided are initialized the same as described above for when the number of initializer clauses is less than the number of members (default member initializers where provided, empty list-initialization otherwise): struct A{ string str;int n=42;int m=-1;}; A{.m=21}// Initializes str with {}, which calls the default constructor// then initializes n with = 42// then initializes m with = 21 struct A{int x;int y;int z;}; A a{.x=1, .z=2};// ok, b.y initialized to 0A b{.y=2, .x=1};// error; designator order does not match declaration orderA c{.y=2};// ok, c.x and c.z are initialized to 0constexpr A d{.z=2};// can be used with constexpr, as opposed to: constexpr A d;static_assert(d.x==0&& d.y==0);// d.x and d.y are initialized to 0 If the aggregate that is initialized with a designated initializer clause has an anonymous union member, the corresponding designated initializer must name one of the members of that anonymous union. Note: out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays are all supported in theC programming language, but are not allowed in C++. struct A{int x, y;};struct B{struct A a;}; struct A a={.y=1, .x=2};// valid C, invalid C++ (out of order)int arr[3]={[1]=5};// valid C, invalid C++ (array)struct B b={.a.x=0};// valid C, invalid C++ (nested)struct A a={.x=1,2};// valid C, invalid C++ (mixed) | (since C++20) |
Arrays of ordinary character types (char,signedchar,unsignedchar),char8_t(since C++20),char16_t,char32_t(since C++11), orwchar_t can be initialized from ordinarystring literals, UTF-8 string literals(since C++20), UTF-16 string literals, UTF-32 string literals(since C++11), or wide string literals, respectively, optionally enclosed in braces. Additionally, an array ofchar orunsignedchar may be initialized by a UTF-8 string literal, optionally enclosed in braces(since C++20). Successive characters of the string literal (which includes the implicit terminating null character) initialize the elements of the array, with anintegral conversion if necessary for the source and destination value(since C++20). If the size of the array is specified and it is larger than the number of characters in the string literal, the remaining characters are zero-initialized.
char a[]="abc";// equivalent to char a[4] = {'a', 'b', 'c', '\0'}; // unsigned char b[3] = "abc"; // Error: initializer string too longunsignedchar 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'};
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 only be used in variable definition, and could not be used in aconstructor initializer list, anew-expression, or temporary object creation due to syntax restrictions.
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++.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_aggregate_bases | 201603L | (C++17) | Aggregate classes with base classes |
__cpp_aggregate_nsdmi | 201304L | (C++14) | Aggregate classes with default member initializers |
__cpp_aggregate_paren_init | 201902L | (C++20) | Aggregate initialization in the form ofdirect initialization |
__cpp_char8_t | 202207L | (C++23) (DR20) | char8_t compatibility and portability fix (allow initialization of (unsignedchar arrays fromUTF-8 string literals) |
__cpp_designated_initializers | 201707L | (C++20) | Designated initializers |
#include <array>#include <cstdio>#include <string> struct S{int x; struct Foo{int i;int j;int a[3];} 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 until CWG 1270:// brace elision only allowed with equals sign int ar[]={1,2,3};// ar is int[3]// char cr[3] = {'a', 'b', 'c', 'd'}; // too many initializer clauseschar 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 aggregatestd::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-initializationunion U{int a;constchar* b;}; 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 [](...){std::puts("Garbage collecting unused variables... Done.");}( s1, s2, s3, s4, ar, cr, ar2d1, ar2d2, ar2d3, std_ar2, std_ar1, u1);} // aggregatestruct base1{int b1, b2=42;}; // non-aggregatestruct base2{ base2(): b3(42){} int b3;}; // aggregate in C++17struct derived: base1, base2{int d;}; derived d1{{1,2},{},4};// d1.b1 = 1, d1.b2 = 2, d1.b3 = 42, d1.d = 4derived d2{{},{},4};// d2.b1 = 0, d2.b2 = 42, d2.b3 = 42, d2.d = 4
Output:
Garbage collecting unused variables... Done.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 413 | C++98 | anonymous bit-fields were initialized in aggregate initialization | they are ignored |
CWG 737 | C++98 | when a character array is initialized with a string literal having fewer characters than the array size, the character elements after the trailing'\0' was uninitialized | they are zero-initialized |
CWG 1270 | C++11 | brace elision was only allowed to be used in copy-list-initialization | allowed elsewhere |
CWG 1518 | C++11 | a class that declares an explicit default constructor or has inherited constructors should could be an aggregate | it is not an aggregate |
CWG 1622 | C++98 | a union could not be initialized with{} | allowed |
CWG 2149 (P3106R1) | C++98 | it was unclear whether brace elision is applicable during array size deduction | applicable |
CWG 2272 | C++98 | a non-static reference member that is not explicitly initialized was copy-initialized from an empty initializer list | the program is ill- formed in this case |
CWG 2610 | C++17 | aggregate types could not have private or protected indirect base classes | allowed |
CWG 2619 | C++20 | the kind of the initialization from designated initializers was unclear | it depends on the kind of the initializer |
P2513R4 | C++20 | a UTF-8 string literal could not initialize an array ofchar orunsignedchar, which was incompatible with C or C++17 | such initialization is valid |
C documentation forStruct and union initialization |