list initialization



Initializes an object from braced-init-list

Contents

 [hide

[edit] Syntax

[edit] direct-list-initialization
 
T object { arg1, arg2, ... };(1) 
 
T { arg1, arg2, ... };(2) 
 
new T { arg1, arg2, ... } (3) 
 
Class { T member { arg1, arg2, ... }; }; (4) 
 
Class::Class() : member{arg1, arg2, ...} {...(5) 
 
[edit] copy-list-initialization
 
T object = {arg1, arg2, ...};(6) 
 
function( { arg1, arg2, ... } ) ;(7) 
 
return { arg1, arg2, ... } ;(8) 
 
object[ { arg1, arg2, ... } ] ;(9) 
 
object = { arg1, arg2, ... } ;(10) 
 
U( { arg1, arg2, ... } ) (11) 
 
Class { T member = { arg1, arg2, ... }; }; (12) 
 

List initialization is performed in the following situations:

  • direct-list-initialization (both explicit and non-explicit constructors are considered)
1) initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)
2) initialization of an unnamed temporary with a braced-init-list
3) initialization of an object with dynamic storage duration with a new-expression, where the initializer is a brace-init-list
4) in a non-static data member initializer that does not use the equals sign
5) in a member initializer list of a constructor if braced-init-list is used
  • copy-list-initialization (only non-explicit constructors may be called)
6) initialization of a named variable with a braced-init-list after an equals sign
7) in a function call expression, with braced-init-list used as an argument and list-initialization initializes the function parameter
8) in a return statement with braced-init-list used as the return expression and list-initialization initializes the returned object
9) in a subscript expression with a user-defined operator[], where list-initialization initializes the parameter of the overloaded operator
10) in an assignment expression, where list-initialization initializes the parameter of the overloaded operator=
11) functional cast expression or other constructor invocations, where braced-init-list is used in place of a constructor argument. Copy-list-initialization initializes the constructor's parameter (note; the type U in this example is not the type that's being list-initialized; U's constructor's parameter is)
12) in a non-static data member initializer that uses the equals sign

[edit] Explanation

The effects of list initialization of an object of type T are:

  • If T is an aggregate type and the initializer list has a single element of the same or derived type (possibly cv-qualified), the object is initialized from that element (by copy-initialization for copy-list-initialization, or by direct-initialization for direct-list-initialization).
  • Otherwise, if T is a character array and the initializer list has a single element that is an appropriately-typed string literal, the array is initialized from the string literal as usual
(since C++14)
  • If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
(until C++14)
  • Otherwise, If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed.
(since C++14)
  • Otherwise, if T is a specialization of std::initializer_list, the T object is direct-initialized or copy-initialized, depending on context, from a prvalue of the same time initialized from (until C++17) the braced-init-list.
  • Otherwise, the constructors of T are considered, in two phases:
  • If the previous stage does not produce a match, all constructors of T participate in overload resolution against the set of arguments that consists of the elements of the braced-init-list, with the restriction that only non-narrowing conversions are allowed. If this stage produces an explicit constructor as the best match for a copy-list-initialization, compilation fails (note, in simple copy-initialization, explicit constructors are not considered at all).
  • Otherwise, if T is a enumeration type that is either scoped or unscoped with fixed underlying type, and if the braced-init-list has only one initializer, and if the conversion from the initializer to the underlying type is non-narrowing, and if the initialization is direct-list-initialization, then the enumeration is initialized with the result of converting the initializer to its underlying type.
(since C++17)
  • Otherwise (if T is not a class type), if the braced-init-list has only one element and either T isn't a reference type or is a reference type that is compatible with the type of the element, T is direct-initialized (in direct-list-initialization) or copy-initialized (in copy-list-initialization), except that narrowing conversions are not allowed.
  • Otherwise, if T is a reference type that isn't compatible with the type of the element, a temporary of the referenced type is list-initialized, and the reference is bound to that temporary (until C++17)the reference is direct-initialized from a prvalue expression of the referenced type that list-initializes its result object (since C++17). (this fails if the reference is a non-const lvalue reference)

[edit] Narrowing conversions

list-initialization limits the allowed implicit conversions by prohibiting the following:

  • conversion from a floating-point type to an integer type
  • conversion from a long double to double or to float and conversion from double to float, except where the source is a constant expression and overflow does not occur
  • conversion from an integer type to a floating-point type, except where the source is a constant expression whose value can be stored exactly in the target type
  • conversion from integer or unscoped enumeration type to integer type that cannot represent all values of the original, except where source is a constant expression whose value can be stored exactly in the target type

[edit] Notes

A braced-init-list is not an expression and therefore has no type, e.g. decltype({1,2}) is ill-formed. Having no type implies that template type deduction cannot deduce a type that matches a braced-init-list, so given the declaration template<class T> void f(T); the expression f({1,2,3}) is ill-formed. A special exception is made for type deduction using the keyword auto , which deduces any braced-init-list as std::initializer_list

Also because braced-init-list has no type, special rules for overload resolution apply when it is used as an argument to an overloaded function call.

Aggregates copy/move initialize directly from single-element braced-init-lists of the same type, but non-aggregates consider initializer_list constructors first:

struct X {
    X() = default;
    X(const X&) = default;
};
 
struct Q {
    Q() = default;
    Q(Q const&) = default;
    Q(std::initializer_list<Q>) {}
};
 
int main() {
  X x;
  X x2 = X { x }; // copy-constructor (not aggregate initialization)
  Q q;
  Q q2 = Q { q }; // initializer-list constructor (not copy constructor)
}
(since C++14)

[edit] Example


#include <iostream>
#include <vector>
#include <map>
#include <string>
 
struct Foo {
    std::vector<int> mem = {1,2,3}; // list-initialization of a non-static member
    std::vector<int> mem2;
    Foo() : mem2{-1, -2, -3} {} // list-initialization of a member in constructor
};
 
std::pair<std::string, std::string> f(std::pair<std::string, std::string> p)
{
    return {p.second, p.first}; // list-initialization in return statement
}
 
int main()
{
    int n0{};     // value-initialization (to zero)
    int n1{1};    // direct-list-initialization
    std::string s1{'a', 'b', 'c', 'd'}; // initializer-list constructor call
    std::string s2{s1, 2, 2};           // regular constructor call
    std::string s3{0x61, 'a'}; // initializer-list ctor is preferred to (int, char)
 
    int n2 = {1}; // copy-list-initialization
    double d = double{1.2}; // list-initialization of a temporary, then copy-init
 
    std::map<int, std::string> m = { // nested list-initialization
           {1, "a"},
           {2, {'a', 'b', 'c'} },
           {3, s1}
    };
 
    std::cout << f({"hello", "world"}).first // list-initialization in function call
              << '\n';
 
    const int (&ar)[2] = {1,2}; // binds a lvalue reference to a temporary array
    int&& r1 = {1}; // binds a rvalue reference to a temporary int
//  int& r2 = {2}; // error: cannot bind rvalue to a non-const lvalue ref
 
//  int bad{1.0}; // error: narrowing conversion
    unsigned char uc1{10}; // okay
//  unsigned char uc2{-1}; // error: narrowing conversion
 
    Foo f;
 
    std::cout << n0 << ' ' << n1 << ' ' << n2 << '\n'
              << s1 << ' ' << s2 << ' ' << s3 << '\n';
    for(auto p: m)
        std::cout << p.first << ' ' << p.second << '\n';
    for(auto n: f.mem)
        std::cout << n << ' ';
    for(auto n: f.mem2)
        std::cout << n << ' ';
}

Compiler messages:

main.cpp: In function 'int main()':
main.cpp:26:12: warning: unused variable 'd' [-Wunused-variable]
     double d = double{1.2}; // list-initialization of a temporary, then copy-init
            ^
main.cpp:37:17: warning: unused variable 'ar' [-Wunused-variable]
     const int (&ar)[2] = {1,2}; // binds a lvalue reference to a temporary array
                 ^~
main.cpp:38:11: warning: unused variable 'r1' [-Wunused-variable]
     int&& r1 = {1}; // binds a rvalue reference to a temporary int
           ^~
main.cpp:42:19: warning: unused variable 'uc1' [-Wunused-variable]
     unsigned char uc1{10}; // okay
                   ^~~

Output:

world
0 1 1
abcd cd aa
1 a
2 abc
3 abcd
1 2 3 -1 -2 -3

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DRApplied toBehavior as publishedCorrect behavior
CWG 1467C++14same-type initialization of aggregates and char arrays was prohibitedsame-type initialization allowed
CWG 1467C++14std::initializer_list constructors had priority over copy constructors for single-element listssingle-element lists initialize directly

[edit] See also



The initialization of UART4 can vary depending on the microcontroller or development board being used. However, here is an example of how to initialize UART4 on a STM32F4 Discovery board using CubeMX and HAL libraries: 1. Open CubeMX and create a new project for your microcontroller or development board. 2. In the "Pinout & Configuration" tab, select "UART4" from the peripherals list. 3. Enable the "Asynchronous" mode and set the baud rate to the desired value. 4. Set the word length, stop bits, and parity according to your application's requirements. 5. Configure the GPIO pins for the UART4 peripheral by selecting the appropriate pins in the "Pinout" tab. 6. Generate the code by clicking on the "Generate" button. 7. Open the generated code and locate the "MX_UART4_Init" function. 8. In this function, you will find the initialization code for UART4. It will look something like this: ``` huart4.Instance = UART4; huart4.Init.BaudRate = 115200; huart4.Init.WordLength = UART_WORDLENGTH_8B; huart4.Init.StopBits = UART_STOPBITS_1; huart4.Init.Parity = UART_PARITY_NONE; huart4.Init.Mode = UART_MODE_TX_RX; huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart4.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart4) != HAL_OK) { Error_Handler(); } ``` 9. This code initializes UART4 with a baud rate of 115200, 8 data bits, 1 stop bit, no parity, and both transmit and receive modes enabled. 10. You can now use the HAL functions to send and receive data over UART4. For example, to transmit a string over UART4, you can use the following code: ``` char* str = "Hello, World!"; HAL_UART_Transmit(&huart4, (uint8_t*)str, strlen(str), HAL_MAX_DELAY); ``` This will send the string "Hello, World!" over UART4.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值