C ++ 11中带有或不带有花括号的初始化差异

问题描述:

我们可以在C ++ 11中以两种方式初始化变量

We can initialize the variable in two ways in C++11

一个:

int abc = 7;

二:

int abc {7};

这两种方法有什么区别?

What is the difference between these two methods?

编译器如何区别对待它们或执行这些代码?

How compiler treats them differently or the way these codes are executed?

简短版



通过 {..} 进行初始化是列表初始化,它禁止缩小转换范围。例如,如果 LLONG_MAX long long int 的最大值,而您的 int 不能表示:

Short version

Initialization via {..} is list-initialization, which prohibits narrowing conversions. For example, if LLONG_MAX is the maximum value of an long long int, and your int cannot represent that:

int x = LLONG_MAX;  // probably accepted with a warning
int x {LLONG_MAX};  // error

类似地:

long long y = /*something*/;

int x = y;  // accepted, maybe with a warning
int x {y};  // error






长版



形式的初始化


Long version

An initialization of the form

T x = a;

复制初始化;两种形式的初始化

T x(a);
T x{a};

直接初始化,[dcl.init] / 15-16 。

is direct-initialization, [dcl.init]/15-16.

[dcl.init] / 14然后说:

[dcl.init]/14 then says:


表格初始化的次数(使用括号或 = )通常无关紧要,但是当初始化程序或要初始化的实体具有类类型时,它就无关紧要;

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.

因此对于非类类型,初始化的 form 无关紧要。但是,这两个直接初始化之间是有区别的:

So for non-class types, the form of the initialization doesn't matter. However, there's a difference between these two direct-initializations:

T x(a);  // 1
T x{a};  // 2

以及类似地,在这两个复制初始化之间:

and similarly, between these two copy-initializations:

T x = a;    // 1
T x = {a};  // 2

即,带有 {..} 使用列表初始化。 {..} 被称为括号初始化列表

Namely, the ones with {..} use list-initialization. The {..} is called a braced-init-list.

所以,当您将 T x = a; T x {a}; 进行比较时,有两个差异:复制与直接初始化,以及非列表与列表初始化。正如其他人已经提到的,以及在上面的引用中,对于非类类型 T ,copy-init和direct-init之间没有区别。但是,list-init和no list-init之间是有区别的。也就是说,我们也可以比较

So, when you compare T x = a; to T x {a};, there are two differences: copy- vs. direct-initialization, and "non-list-" vs. list-initialization. As already mentioned by others and in the quote above, for non-class types T, there's no difference between copy- and direct-init. However, there's a difference between list-init and no list-init. That is, we could as well compare

int x (a);
int x {a};

在这种情况下,列表初始化禁止缩小转换范围。缩小转换在[dcl.init.list] / 7中定义为:

List-initialization in this case prohibits narrowing conversions. Narrowing conversions are defined in [dcl.init.list]/7 as:


缩小转换是隐式转换

A narrowing conversion is an implicit conversion


  • 从浮点类型到整数类型,或者

  • from a floating-point type to an integer type, or

long double double float ,或从 double float ,除非源是常量表达式,并且转换后的实际值在以下范围内:可以用
表示(即使不能精确表示),或者

from long double to double or float, or from double to float, except where the source is a constant expression and the actual value after conversion is within the range of values that can be represented (even if it cannot be represented exactly), or

从整数类型或无作用域枚举类型到浮点类型,除非源
是一个常量表达式,并且转换后的实际值将适合目标类型,并且
在转换回原始类型时会产生原始值,或者

from an integer type or unscoped enumeration type to a floating-point type, except where the source is a constant expression and the actual value after conversion will fit into the target type and will produce the original value when converted back to the original type, or

从整数类型或无作用域枚举类型到无法表示的整数类型输入原始类型的所有
值,除非源是一个常数表达式,其整数
促销后的值将适合目标类型。

from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.