在c++ 11中,Are ={}和{}样式的初始化是相同的

Are ={} and {}-style initializations the same in C++11?

本文关键字:初始化 c++ 样式 Are      更新时间:2023-10-16

c++ 11引入了{}样式的初始化。但是这两种形式

T x {...};
T x = {...};

一样吗?

它们并不完全相同。也许这可以用一个反例来说明:

struct Foo
{
  explicit Foo(std::initializer_list<int>) {}
};
int main()
{
  Foo f0{1, 2, 3};    // OK
  Foo f1 = {1, 2, 3}; // ERROR
}
因此,第二个变体要求该类型可以从初始化列表隐式构造,而第一个版本则不需要。注意,这同样适用于形式为Foo(int, int, int)的构造函数。我随意选择了initializer_list<int>作为例子。

这将影响遵循"显式无处不在"哲学编写的某些类型(即人们在c++ 03代码中将多参数构造函数标记为explicit,即使在该标准中没有意义)

除了在juanchopanza的回答中解释的差异之外,当涉及到auto带括号的初始化列表的类型推导时,直接列表初始化复制列表初始化之间还有另一个差异,一个突破性的变化。虽然它没有作为c++ 14的一部分添加(最后一个问题),但问题已经确定,何时实现取决于委员会。

例如,

auto foo = {42};  // deduces foo as an initializer_list<int>
auto foo{42};     // deduces foo as an int

因此,直接列表初始化永远不会从实参中推导出initializer_list。因此,下面的代码将是病态的。

auto foo{1,2};    // cannot have multiple initializers for 
                  // direct-list-initialization when deducing type

但这是可以的:

auto foo = {1,2}; // copy-list-initialization still deduces initializer_list<int>

同样适用于lambda表达式中的一般化捕获。引用N3912

[x{5}](){};        // x is int
[x{1,2}](){};      // ill-formed, no multiple initializers with direct-init
[x = {5}](){};     // ok, x is an initializer_list<int> with one element
[x = {1,2}](){};   // ok, x is an initializer_list<int> with two elements

语法在一种情况下使用它们意味着不同的东西

struct A { };
namespace X {
  struct A final {};
  struct A final = {};
}
在第一个例子中,我们定义了一个名为A的结构体,在第二个例子中,我们定义了一个名为final的对象。