如果不是 intializer_list,什么是花括号括起来的列表?

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

我在这里问了一个问题:涉及非功能代码:

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

我相信 lambda 试图 return 一个 intializer_list(那很糟糕,不要那样做。)但是我得到了一个 :

It's not an initializer_list, it's an initializer list. Two different things.

我只是认为任何时候你做一个花括号列表你都在创建一个 intializer_list。如果不是这样,花括号中的列表是什么?

它是一个 braced-init-listbraced-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?

I just thought that any time you did a curly-braced list you were creating an intializer_list.

不正确。

If that's not what's happening, what is a list in curly-braces?

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

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

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

再次声明,创建数组是一种语法形式。

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

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

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

  2. Initializer list:在list-initialization中使用的braced-init-list初始化器的名称。

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

一些示例:

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

使用时你有两个不同的东西{}

  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