如果不是 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-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,然后将其传递给接受 std::initializer_listfoo 的构造函数.

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&lt;int&gt;【参考方案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,它改变了一些涉及autostd::initializer_list 的规则。

【讨论】:

以上是关于如果不是 intializer_list,啥是花括号封闭列表?的主要内容,如果未能解决你的问题,请参考以下文章

ByteBuffer,啥是检测是不是需要翻转的干净方法

Ecmascript语句

我可以在 Heroku 上托管网站吗?如果没有,啥是类似 PaaS 的解决方案?

请问啥是LPC

ARM的UART中,啥是FIFO模式,在进行串口通信时不是一定要用到FIFO的吗?对于UTRSTATn很不理解。谢谢

究竟啥是超级视图?