在 C++ 中我们可以通过两种方式初始化变量
一:
int abc = 7;
两个:
int abc {7};
这两种方法有什么区别?编译器是否以不同的方式对待它们,或者代码的执行方式是否存在差异?
最佳答案
简短版本
通过{..}
进行的初始化是列表初始化,它禁止缩小转换。例如,如果 LLONG_MAX
是 long long int
的最大值,而您的 int
无法表示:
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
<小时/>
长版
表单的初始化
T x = a;
是复制初始化;任一形式的初始化
T x(a);
T x{a};
是直接初始化,[dcl.init]/15-16。
[dcl.init]/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.
因此,对于非类类型,初始化的形式并不重要。但是,这两种直接初始化之间存在差异:
T x(a); // 1
T x{a}; // 2
同样,在这两个复制初始化之间:
T x = a; // 1
T x = {a}; // 2
也就是说,带有 {..}
的使用列表初始化。 {..}
称为braced-init-list。
因此,当您将 T x = a;
与 T x {a};
进行比较时,有两个差异:复制与复制.直接初始化,以及“非列表”与列表初始化。正如其他人以及上面的引用中已经提到的,对于非类类型 T
,复制初始化和直接初始化之间没有区别。然而,list-init 和 no list-init 之间是有区别的。也就是说,我们也可以比较
int x (a);
int x {a};
在这种情况下,列表初始化会禁止缩小转换范围。缩小转换在 [dcl.init.list]/7 中定义为:
A narrowing conversion is an implicit conversion
from a floating-point type to an integer type, or
from
long double
todouble
orfloat
, or fromdouble
tofloat
, 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), orfrom 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.
关于c++ - C++ 中带或不带花括号的初始化差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21150067/