如果不是 intializer_list,啥是花括号封闭列表?
Posted
技术标签:
【中文标题】如果不是 intializer_list,啥是花括号封闭列表?【英文标题】:What Is a Curly-Brace Enclosed List If Not an intializer_list?如果不是 intializer_list,什么是花括号封闭列表? 【发布时间】:2016-10-07 12:50:07 【问题描述】:我在这里问了一个问题: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
。如果这不是正在发生的事情,那么大括号中的列表是什么?
【问题讨论】:
只是:错误:返回初始化列表。 @DieterLücking 你的错误肯定比我高。第一次尝试时我什至没有收到警告,尽管如链接问题中所述,这是不是好的代码。 @JonathanMee 下面的 SO 问题也有一些有用的知识答案:***.com/questions/29200036/… @Arunmu 你是说这些只是与initializer_list
相关的好消息吗?因为如果你说它直接相关,我错过了如何。
@JonathanMee 是的,很高兴知道:)。我不知道制作 initializer_list 实例需要一些编译器魔法:)
【参考方案1】:
使用时你有两个不同的东西
-
一种类型
std::initializer_list<T>
,其中的值可以隐式转换为T
可以使用列表值初始化的类型。
第一种类型强制使用同构列表,第二种类型不强制。在下一个示例中:
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
【讨论】:
【参考方案2】:这是一个 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
,然后将其传递给接受 std::initializer_list
的 foo
的构造函数.
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 x3 deduce an initializer_list?获得有关此行为历史以及更改原因的更多信息:Why does auto x3 deduce an initializer_list?
【讨论】:
如果我这样做,auto foo = 1, 2, 3, 4, 5
foo
的类型是什么?是否保证是intializer_list
?
@JonathanMee 我认为更新现在应该涵盖这一点。
@T.C.我什至没有看到“非终端”这个词你在说什么?
@JonathanMee 你认为 braced-init-list 是什么?
@JonathanMee en.wikipedia.org/wiki/Terminal_and_nonterminal_symbols braced-init-list 是 C++ 语法中此构造的非终结符。【参考方案3】:
我只是认为,任何时候你做一个花括号的列表,你都是在创建一个
intializer_list
。
这是不正确的。
如果不是这样,花括号中的列表是什么?
struct Foo int a; int b;;
Foo f = 10, 20;
10, 20
部分不是initializer_list
。它只是一种使用对象列表创建另一个对象的语法形式。
int a[] = 10, 20, 30;
再一次,它是一种创建数组的语法形式。
语法形式的名称是braced-init-list
。
【讨论】:
所以我问了同样的问题,@NathanOliver:“如果我这样做,auto foo = 1, 2, 3, 4, 5
foo
的类型是什么?它保证是 intializer_list
吗?”
那将是std::initializer_list<int>
。【参考方案4】:
这里有三个不同但相关的概念:
braced-init-list:在某些上下文中与大括号括起来的列表相关的语法规则。
Initializer list:在 list-initialization 中使用的 braced-init-list 初始化器的名称。
std::initializer_list
:包装临时数组的类,该数组是在涉及 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,它改变了一些涉及auto
和std::initializer_list
的规则。
【讨论】:
以上是关于如果不是 intializer_list,啥是花括号封闭列表?的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 Heroku 上托管网站吗?如果没有,啥是类似 PaaS 的解决方案?