简体   繁体   English

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

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

Is there any subtle difference between these two ways of initializing variables in C++11? 这两种在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 };

Can the latter be used for all the same cases as the first one? 后者可以用于与第一个相同的所有情况吗?

Stroustrup claims in TCPL4ED that the first way is the only one that can be used in every context, and thus recommends it. Stroustrup在TCPL4ED中声称第一种方式是唯一可以在每个上下文中使用的方法,因此推荐它。 Later on, he seems to imply that the second one is just a different way of writing the first one. 后来,他似乎暗示第二个只是写第一个的另一种方式。

1. 1。

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

Is a direct-list-initialization . 直接列表初始化 It means that it is initialized with a constructor taking an initializer list. 这意味着它是使用构造函数初始化列表初始化的。

Constructor : 构造函数:

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

2. 2。

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

Is a copy-list-initialization . 复制列表初始化


The standard is pretty clear : 标准很清楚:

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

List-initialization is initialization of an object or reference from a braced-init-list. 列表初始化是从braced-init-list初始化对象或引用。 Such an initializer is called an initializer list, and the comma-separated initializer-clauses of the list are called the elements of the initializer list. 这样的初始化程序称为初始化程序列表,列表的逗号分隔的初始化程序子句称为初始化程序列表的元素。 An initializer list may be empty. 初始化列表可以为空。 List-initialization can occur in direct-initialization or copyinitialization contexts; 列表初始化可以在直接初始化或copyinitialization上下文中进行; list-initialization in a direct-initialization context is called direct-list-initialization and list-initialization in a copy-initialization context is called copy-list-initialization. 直接初始化上下文中的列表初始化称为直接列表初始化,复制初始化上下文中的列表初始化称为复制列表初始化。 [ Note: List-initialization can be used : [注意:可以使用列表初始化:

  • as the initializer in a variable definition 作为变量定义中的初始化器

[...] [...]

Example : 示例:

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

For the difference between both, we should go a little bit further : 对于两者之间的差异,我们应该进一步:

13.3.1.7 Initialization by list-initialization [over.match.list] 13.3.1.7按列表初始化初始化[over.match.list]

  • For direct-list-initialization , the candidate functions are all the constructors of the class T. 对于直接列表初始化 ,候选函数是类T的所有构造函数。
  • For copy-list-initialization , the candidate functions are all the constructors of T. However, if an explicit constructor is chosen, the initialization is ill-formed. 对于复制列表初始化 ,候选函数是T的所有构造函数。 但是,如果选择了explicit构造函数,则初始化是错误的。 [ Note: This restriction only applies if this initialization is part of the final result of overload resolution — end note ] [注意:此限制仅适用于此初始化是重载解析的最终结果的一部分 - 结束注释]

The purpose of uniform initialization was (in part) to remove the difference between these two constructs. 统一初始化的目的是(部分) 消除这两种结构之间的差异。 To ensure that they would have the same functionality. 确保它们具有相同的功能。

Sadly, they failed. 可悲的是,他们失败了。 There is exactly one difference between direct-list-initialization (ie: T t{...} ) and copy-list-initialization (ie: T t = {...} ). 直接列表初始化(即: T t{...} )和复制列表初始化(即: T t = {...} )之间只有一个区别 You don't need a copy/move constructor for copy-list-initialization (despite the name); 您不需要复制/移动构造函数进行复制列表初始化(尽管名称); section 8.5.4 doesn't list that as a requirement. 第8.5.4节没有将其列为要求。 There's no notion of a temporary being constructed that might be elided away. 没有一个临时建造的概念可能会被遗弃。 They have identical behavior except : 他们有相同的行为, 除了

Copy-list-initialization will fail if it selects an explicit constructor. 如果选择explicit构造函数,则复制列表初始化将失败。 That's the only difference. 这是唯一的区别。

It's hard to give a quote from the spec, because there are only 3 mentions of what copy-list-initialization is. 很难从规范中引用一个引用,因为只有3个提到复制列表初始化是什么。 One is in 8.5.4, where it defines that copy-list-initialization is a form of list-initialization, another stating that returning a braced-init-list uses copy-list-initialization. 一个是在8.5.4中,它定义了复制列表初始化是列表初始化的一种形式,另一个说明返回一个braced-init-list使用复制列表初始化。 And the last in 13.3.1.7, where it states the above exception: 13.3.1.7中的最后一个,它说明了上述异常:

In copy-list-initialization, if an explicit constructor is chosen, the initialization is ill-formed. 在copy-list-initialization中,如果选择了explicit构造函数,则初始化是错误的。

So that's the only difference. 这是唯一的区别。

One difference which comes to mind is that the first form can be used even if the constructor is declared explicit while the second cannot. 我想到的一个区别是,即使构造函数被声明为explicit ,第二种形式也可以使用,而第二种形式则不然。 Sorry but, @Timothy Shields and @Tomek are wrong, both statements are direct initializations, not copy initialization. 抱歉,但@Timothy Shields和@Tomek错了,两个语句都是直接初始化,而不是复制初始化。

I guess this is similar to the case with normal constructors (ie not using initializer lists). 我想这与普通构造函数的情况类似(即不使用初始化程序列表)。 The first choice is a construction using (in this case) constructor taking initializer list constructor. 第一个选择是使用(在这种情况下)构造函数采用初始化列表构造函数的构造。 The other choice is a temporary created with initializer list constructor and then the variable is copy-constructed from that. 另一个选择是使用初始化列表构造函数创建的临时选项,然后该变量由该复制构造。 Temporary then goes away. 临时然后消失。 Note that the latter usually skips temporary and copy destruction as (N)RVO kicks in BUT the latter requires that your class has accessible copy constructor at the point of definition. 请注意,后者通常会跳过临时和复制销毁,因为(N)RVO会启动,但后者要求您的类在定义时具有可访问的复制构造函数。 At least this is what I remember from C++03, it MAY have changed in C++11. 至少这是我记得的C ++ 03,它可能在C ++ 11中有所改变。

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

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