繁体   English   中英

将'='添加到初始化列表之间是否有任何细微差别?

[英]Is there any subtle difference between prepending '=' to initializer lists?

这两种在C ++ 11中初始化变量的方法之间有什么细微的差别吗?

  1. vector<double> v { 0.0, 1.1, 2.2, 3.3 };

  2. vector<double> v = { 0.0, 1.1, 2.2, 3.3 };

后者可以用于与第一个相同的所有情况吗?

Stroustrup在TCPL4ED中声称第一种方式是唯一可以在每个上下文中使用的方法,因此推荐它。 后来,他似乎暗示第二个只是写第一个的另一种方式。

1。

vector<double> v { 0.0, 1.1, 2.2, 3.3 };

直接列表初始化 这意味着它是使用构造函数初始化列表初始化的。

构造函数:

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );

2。

vector<double> v = { 0.0, 1.1, 2.2, 3.3 };

复制列表初始化


标准很清楚:

8.5.4列表初始化[dcl.init.list]

列表初始化是从braced-init-list初始化对象或引用。 这样的初始化程序称为初始化程序列表,列表的逗号分隔的初始化程序子句称为初始化程序列表的元素。 初始化列表可以为空。 列表初始化可以在直接初始化或copyinitialization上下文中进行; 直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化。 [注意:可以使用列表初始化:

  • 作为变量定义中的初始化器

[...]

示例:

  std::complex<double> z{1,2}; [...] std::map<std::string,int> anim = { {"bear",4}, {"cassowary",2}, {"tiger",7} }; 

对于两者之间的差异,我们应该进一步:

13.3.1.7按列表初始化初始化[over.match.list]

  • 对于直接列表初始化 ,候选函数是类T的所有构造函数。
  • 对于复制列表初始化 ,候选函数是T的所有构造函数。 但是,如果选择了explicit构造函数,则初始化是错误的。 [注意:此限制仅适用于此初始化是重载解析的最终结果的一部分 - 结束注释]

统一初始化的目的是(部分) 消除这两种结构之间的差异。 确保它们具有相同的功能。

可悲的是,他们失败了。 直接列表初始化(即: T t{...} )和复制列表初始化(即: T t = {...} )之间只有一个区别 您不需要复制/移动构造函数进行复制列表初始化(尽管名称); 第8.5.4节没有将其列为要求。 没有一个临时建造的概念可能会被遗弃。 他们有相同的行为, 除了

如果选择explicit构造函数,则复制列表初始化将失败。 这是唯一的区别。

很难从规范中引用一个引用,因为只有3个提到复制列表初始化是什么。 一个是在8.5.4中,它定义了复制列表初始化是列表初始化的一种形式,另一个说明返回一个braced-init-list使用复制列表初始化。 13.3.1.7中的最后一个,它说明了上述异常:

在copy-list-initialization中,如果选择了explicit构造函数,则初始化是错误的。

这是唯一的区别。

我想到的一个区别是,即使构造函数被声明为explicit ,第二种形式也可以使用,而第二种形式则不然。 抱歉,但@Timothy Shields和@Tomek错了,两个语句都是直接初始化,而不是复制初始化。

我想这与普通构造函数的情况类似(即不使用初始化程序列表)。 第一个选择是使用(在这种情况下)构造函数采用初始化列表构造函数的构造。 另一个选择是使用初始化列表构造函数创建的临时选项,然后该变量由该复制构造。 临时然后消失。 请注意,后者通常会跳过临时和复制销毁,因为(N)RVO会启动,但后者要求您的类在定义时具有可访问的复制构造函数。 至少这是我记得的C ++ 03,它可能在C ++ 11中有所改变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM