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

Ric*_*aez 13 c++ 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 };

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

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

Pie*_*aud 8

1.

vector<double> v { 0.0, 1.1, 2.2, 3.3 };
Run Code Online (Sandbox Code Playgroud)

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

构造函数:

vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

2.

vector<double> v = { 0.0, 1.1, 2.2, 3.3 };
Run Code Online (Sandbox Code Playgroud)

复制列表初始化.


标准很清楚:

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} };
Run Code Online (Sandbox Code Playgroud)

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

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

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


Nic*_*las 5

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

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

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

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

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

这是唯一的区别.