什么是Curly-Brace附上列表如果不是intializer_list?

时间:2016-06-07 14:40:19

标签: c++ initialization initializer-list initializer curly-braces

我在这里问了一个问题:Lifetime Extension of a initializer_list return涉及非功能性代码:

const auto foo = [](const auto& a, const auto& b, const auto& c) { return {a, b, c}; };

我相信lambda试图返回intializer_list(这很糟糕,不要这样做。)但是我得到了comment

  

它不是initializer_list,它是初始化列表。两件不同的事情。

我只是想到,只要你做了一个花括号列表,你就创建了一个intializer_list。如果那不是正在发生的事情,花括号中的列表是什么?

4 个答案:

答案 0 :(得分:29)

这是 braced-init-list braced-init-list 存在于std::initializer_list之前,用于initialize aggregates

int arr[] = {1,2,3,4,5};

上面使用了 braced-init-list 来初始化数组,没有创建std::initializer_list。另一方面,当你做

std::vector<int> foo = {1,2,3,4,5};

foo不是聚合,因此 braced-init-list 用于创建std::initializer_list,其转而传递给foo的构造函数接受std::initializer_list

有关 braced-init-list 的注意事项是没有类型,因此开发了与其一起使用的特殊规则auto。它具有以下行为(自采用N3922

以来
auto x1 = { 1, 2 }; // decltype(x1) is std::initializer_list<int>
auto x2 = { 1, 2.0 }; // error: cannot deduce element type
auto x3{ 1, 2 }; // error: not a single element
auto x4 = { 3 }; // decltype(x4) is std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) is int

您可以在以下位置获取有关此行为的历史记录以及更改原因的详细信息:Why does auto x{3} deduce an initializer_list?

答案 1 :(得分:12)

这里有三个不同但相关的概念:

  1. braced-init-list :在某些上下文中与大括号括起的列表相关联的语法规则。

  2. 初始化列表:列表初始化中使用的 braced-init-list 初始值设定项的名称。

  3. std::initializer_list:包含临时数组的类,该数组在某些涉及 braced-init-list 的上下文中创建。

  4. 一些例子:

    //a braced-init-list and initializer list, 
    //but doesn't create a std::initializer_list
    int a {4}; 
    
    //a braced-init-list and initializer list,
    //creates a std::initializer_list
    std::vector b {1, 2, 3};
    
    //a braced-init-list and initializer list,
    //does not create a std::initializer_list (aggregate initialization)
    int c[] = {1, 2, 3};
    
    //d is a std::initializer_list created from an initializer list
    std::initializer_list d {1, 2, 3};
    
    //e is std::initializer_list<int>
    auto e = { 4 };
    
    //f used to be a std::initializer_list<int>, but is now int after N3922
    auto f { 4 };
    

    您可能需要阅读N3922,这改变了涉及autostd::initializer_list的一些规则。

答案 2 :(得分:7)

  

我只是想到,只要你做了一个花括号列表,你就创建了一个intializer_list

这不正确。

  

如果那不是正在发生的事情,那么大括号中的列表是什么?

struct Foo {int a; int b;};
Foo f = {10, 20};

{10, 20}部分不是initializer_list。它只是一种使用对象列表来创建另一个对象的语法形式。

int a[] = {10, 20, 30};

再一次,它是一种创建数组的语法形式。

句法形式的名称是braced-init-list

答案 3 :(得分:1)

使用{}

时,您有两件不同的事情
  1. 类型std::initializer_list<T>,其值可以隐式转换为T
  2. 可以使用列表值初始化的类型。
  3. 第一种类型强制使用同类列表而第二种类型不强制。在下一个例子中:

    struct S{ 
        int a; 
        string b 
    };
    
    void f1( S s );
    void f2( int i );
    void f3( std::initializer_list<int> l );
    
    f1( {1, "zhen"} ); // construct a temporal S
    f2( {1} );         // construct a temporal int
    f3( {1,2,3} );     // construct a temporal list of ints
    

    函数f1和f2使用第一种类型而f3使用第二种类型。您应该知道,如果存在歧义,则首选std :: initializer_list。 E.g:

    void f( S s );
    void f( int i );
    void f( std::initializer_list<int> l );
    
    f( {1, "zhen"} ); // calls with struct S
    f( {1} );         // calls with int list with one element
    f( {1,2,3} );     // calls with int list with three elements