如果不是intializer_list,什么是大括号封闭列表

What Is a Curly-Brace Enclosed List If Not an intializer_list?

本文关键字:列表 什么 intializer list 如果不      更新时间:2023-10-16

我在这里问了一个问题:涉及非功能性代码的initializer_list返回的生命周期延长:

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

我相信 lambda 试图返回一个intializer_list(这很糟糕,不要那样做。但我得到了一条评论:

它不是一个initializer_list,它是一个初始值设定项列表。两件不同的事情。

我只是认为,任何时候你做一个卷曲列表,你都在创建一个intializer_list。如果不是正在发生的事情,那么大括号中的列表是什么?

它是一个大括号的初始化列表。 在std::initializer_list之前就存在一个大括号的初始化列表,用于初始化聚合。

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

上面使用大括号的初始化列表来初始化数组,没有创建std::initializer_list。 另一方面,当你这样做时

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

foo 不是聚合,因此大括号 init-list 用于创建一个std::initializer_list,该又传递给接受std::initializer_listfoo 的构造函数。

关于大括号初始化列表需要注意的一件事是它没有类型,因此开发了特殊的规则来使用它和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

您可以在以下位置获得有关此行为的历史以及更改原因的更多信息:为什么 auto x{3} 会推断出initializer_list?

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

    大括号
  1. 初始化列表:在某些上下文中与大括号括起来的列表相关联的语法规则。

  2. 初始值设定项列表:列表初始化
  3. 中使用的大括号初始化列表初始值设定项的名称。

  4. std::initializer_list:一个包装临时数组的类,该数组在某些上下文中创建,涉及大括号初始化列表s。

一些例子:

//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的规则。

我只是认为,任何时候你做一个卷曲的支撑列表,你都在创建一个intializer_list

这是不正确的。

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

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

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

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

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

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

使用{}时,您有两种不同的东西

  1. 一种类型std::initializer_list<T>,其中的值可以隐式转换为T
  2. 可以使用列表的值初始化的类型。
第一种类型强制使用

同构列表,第二种类型则不强制使用。在下一个示例中:

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。例如:

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