带双花括号的向量初始化:std :: string vs int [英] Vector initialization with double curly braces: std::string vs int

查看:170
本文介绍了带双花括号的向量初始化:std :: string vs int的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此问题的答案中:初始化vector< string>带有双花括号的

它显示为

vector<string> v = {{"a", "b"}};

将调用 std :: vector 构造函数使用一个元素 initializer_list 。因此,向量中的第一个(也是唯一一个)元素将由 { a, b} 构造。这会导致不确定的行为,但这超出了这里的重点。

will call the std::vector constructor with an initializer_list with one element. So the first (and only) element in the vector will be constructed from {"a", "b"}. This leads to undefined behavior, but that is beyond the point here.

我发现的是

std::vector<int> v = {{2, 3}};

将调用 std :: vector 构造函数两个元素初始化程序列表

为什么这种行为方式不同的原因?

Why is the reason for this difference in behavior?

推荐答案

类类型的列表初始化的规则基本上是:首先,仅考虑进行重载解析std :: initializer_list 构造函数,然后,如有必要,对所有构造函数进行重载解析(这是 [over.match.list] )。

The rules for list initialization of class types are basically: first, do overload resolution only considering std::initializer_list constructors and then, if necessary, do overload resolution on all the constructors (this is [over.match.list]).

初始化 std :: initializer_list<时; E> 从初始化列表中,就好像我们从 N 元素中实现了 const E [N] 在初始化列表中(来自 [dcl.init.list] / 5

When initializing a std::initializer_list<E> from an initializer list, it's as if we materialized a const E[N] from the N elements in the initializer list (from [dcl.init.list]/5).

对于 vector< string> v = {{ a, b}}; 我们首先尝试 initializer_list< string> 构造函数,这将涉及尝试初始化1个常量字符串的数组,其中一个 string 初始化为 { a, b} 。这是可行的,因为 string 的迭代器对构造函数,所以我们最终得到了一个包含单个字符串的向量(UB为UB,因为我们违反该字符串构造函数的先决条件)。

For vector<string> v = {{"a", "b"}}; we first try the initializer_list<string> constructor, which would involve trying to initialize an array of 1 const string, with the one string initialized from {"a", "b"}. This is viable because of the iterator-pair constructor of string, so we end up with a vector containing one single string (which is UB because we violate the preconditions of that string constructor). This is the easy case.

对于 vector< int> v = {{2,3}}; ,我们首先尝试 initializer_list< int> 构造函数,这将涉及尝试初始化1的数组 const int ,其中一个 int 初始化为 {2,3} 。这是不可行的。

For vector<int> v = {{2, 3}}; we first try the initializer_list<int> constructor, which would involve trying to initialize an array of 1 const int, with the one int initialized from {2, 3}. This is not viable.

因此,我们考虑所有 vector 构造函数,重做重载解析。现在,我们得到了两个可行的构造函数:

So then, we redo overload resolution considering all the vector constructors. Now, we get two viable constructors:


  • vector(vector&&) ,因为当我们递归地初始化参数时,初始化列表将为 {2,3} -我们将尝试使用该数组初始化2个 const int ,这是可行的。

  • vector(std :: initializer_list< int>)。这次不是来自普通的列表初始化世界,而是直接从相同的 {2,3} initializer_list >初始化程序列表,出于相同的原因也是可行的。

  • vector(vector&& ), because when we recursively initialize the parameter there, the initializer list would be {2, 3} - with which we would try to initialize an array of 2 const int, which is viable.
  • vector(std::initializer_list<int> ), again. This time not from the normal list-initialization world but just direct-initializing the initializer_list from the same {2, 3} initializer list, which is viable for the same reasons.

要选择哪个构造函数,我们必须进入 [over.ics.list] ,其中 vector(vector&&)构造函数是用户定义的转换顺序,但 vector(initializer_list< int>)构造函数为 identity ,因此是首选。

To pick which constructor, we have to go to into [over.ics.list], where the vector(vector&& ) constructor is a user-defined conversion sequence but the vector(initializer_list<int> ) constructor is identity, so it's preferred.

为了完整起见, vector(vector const&)为也是可行的,但是出于其他原因,我们宁愿将move构造函数比于copy构造函数。

For completeness, vector(vector const&) is also viable, but we'd prefer the move constructor to the copy constructor for other reasons.

这篇关于带双花括号的向量初始化:std :: string vs int的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆