T t {x} 和 T t = { x } 对于整数或枚举类型的区别?

Difference between T t {x} and T t = { x } for integral or enumeration type?

在 C++14 中:

对于任何整数或枚举类型 T 以及对于任何表达式 expr:

有没有区别:

struct S { T t { expr }; };

struct S { T t = { expr }; };

更新:

我到了 [dcl.init.list]p3b5 上面写着:

If the initializer list has a single element of type E and either T is not a reference type or its referenced type is reference-related to E, the object or reference is initialized from that element.

我相信这句话适用于 direct-list-initializationcopy-list-initialization.

所以我认为答案是否定的,没有区别。

如果您查看 direct initialization and copy initialization 参考文献,您会发现相同的词:

if T is a non-class type, standard conversions are used, if necessary, to convert the value of other to the cv-unqualified version of T

所以应该没有区别。这些初始化的区别仅适用于 class 类型:copy initialization does not consider explicit constructors and explicit 用户定义的转换运算符, 直接初始化 即可。整型和枚举类型都没有。

编辑:
@ᐅ Johannes Schaub - litb ᐊ answered a relative question to this one(仅关于括号,而不是大括号)并且他引用了 8.5/14 类似的措辞(强调我的):

The form of initialization (using parentheses or =) is generally insignificant, but does matter when the initializer or the entity being initialized has a class type; see below. If the entity being initialized does not have class type, the expression-list in a parenthesized initializer shall be a single expression.

我也找不到标准中的 {} 对应项。我希望这足以支持 没有区别 答案。

  1. struct S {T t { expr };}; 是非静态数据成员初始值设定项 不使用等号
  2. struct S{T t = { expr };}; 是非静态数据成员初始值设定项 使用等号

第一种情况是直接列表初始化,而第二种情况是复制列表初始化

直接列表初始化复制列表初始化的区别在于第一种情况 显式和非显式构造函数都被考虑,而对于第二个 非显式构造函数可以被调用。

为了澄清,请考虑以下示例:

struct Foo {
  int i;
  explicit Foo(int i_) : i(i_) {}
};

struct Bar {
  Foo f {1};  
};

Live Demo

在此示例中,Foo 具有一个 explicit 构造函数,并且 Bar 直接初始化其类型 Foo 的成员 f。示例代码编译得很好,因为对于直接初始化,explicitnon-explicit 构造函数都被考虑在内。

现在我们通过转换不使用等号的非静态数据成员初始值设定项来改变示例,即直接列表初始化到使用等号的非静态数据成员初始值设定项的情况,这是复制列表初始化的情况。

struct Foo {
  int i;
  explicit Foo(int i_) : i(i_) {}
};

struct Bar {
  Foo f = {1};  
};

Live Demo

现在上面的例子没有编译并发出错误:

error: chosen constructor is explicit in copy-initialization

这是预料之中的,因为正如在复制列表初始化中已经提到的那样,只能调用非显式构造函数。

现在对于枚举数和其他整数类型,上面显示的差异将不适用(即不涉及构造函数)。因此,这两个语句(即 [1] 和 [2])将是等价的。

但为了完整起见,让我们考虑以下示例:

enum class Foo {A, B, C};

struct Bar {
  Foo f{Foo::A};  
};

enum class Foo {A, B, C};

struct Bar {
  Foo f = {Foo::A};  
};

这两个示例都可以正常编译。

还要考虑以下示例:

struct Bar {
  int i {1};  
};

struct Bar {
  int i = {1};  
};

两个示例都可以正常编译。