30

我问一个问题在这里:Lifetime Extension of a initializer_list return涉及非功能代码:如果不是intializer_list,什么是大括号括起来的列表?

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

我相信拉姆达试图返回intializer_list(这是很糟糕,不这样做)。但我有一个comment

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

我只是认为,只要你做了一个卷曲支撑列表,你正在创建一个intializer_list。如果这不是所发生的事情,花括号中的列表是什么?

+0

它只是:错误:返回初始化列表。 –

+1

@DieterLücking你必须让你的错误比我更高。我第一次尝试这种方法时甚至没有收到警告,但正如链接问题所述,这是*不是*好的代码。 –

+0

@JonathanMee下方,以便问题也有一些有用的方知答案:http://stackoverflow.com/questions/29200036/is-providing-a-private-constructor-for-initializer-list-conforming – Arunmu

回答

10

有三种不同的,但相关的概念在这里:

  1. 支撑,初始化列表:在某些情况下花括号封闭列表相关的语法规则。

  2. 初始化列表:在列表初始化使用支撑,初始化列表初始化的名称。

  3. std::initializer_list:一个包装临时数组的类,它在一些涉及braced-init-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规则。

28

这是一个braced-init-list。 A braced-init-liststd::initializer_list之前存在,并且用于initialize aggregates

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

上面使用的支撑-INIT列表初始化数组,没有std::initializer_list被创建。在另一方面,当你做

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

foo不是汇总所以支撑,初始化列表用于创建一个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?

+0

所以如果我这样做,'auto foo = {1,2,3,4,5}'foo'的类型是什么?它保证是一个'intializer_list'吗? –

+1

@JonathanMee我认为这个更新应该包括现在。 – NathanOliver

+0

我希望我们有一个比非终端更好的名字... –

7

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

+0

所以我问的同样的问题,@NathanOliver:“如果我这样做,'auto foo = {1,2,3,4,5}''foo'的类型是什么?它保证是'intializer_list'吗? “ –

+1

这将是一个'std :: initializer_list '。 –

1

你有两个不同的事情,当使用{}

  1. A型std::initializer_list<T>其中的值可以隐式转换为T
  2. 可以用列表的值来初始化A型。

第一种强制均匀的名单,而第二类则没有。在下一个示例中:

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 
相关问题