我们可以在C ++ 11中以两种方式初始化变量
一:
int abc = 7;
两个
int abc {7};
这两种方法有什么区别?
编译器如何区别对待它们或执行这些代码的方式?
答案 0 :(得分:38)
通过{..}
进行初始化是列表初始化,禁止缩小转换次数。例如,如果LLONG_MAX
是long long int
的最大值,而您的int
不能代表:{/ p>
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然后说:
初始化的形式(使用括号或
=
)通常是无关紧要的,但是当初始化器或正在初始化的实体具有类类型时,它确实很重要;见下文。
因此,对于非类类型,初始化的表单无关紧要。但是,这两个直接初始化之间存在差异:
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
,copy-init和direct-init之间没有区别。但是,list-init和没有list-init之间存在差异。也就是说,我们也可以比较
int x (a);
int x {a};
在这种情况下,列表初始化禁止缩小转换次数。缩小转换在[dcl.init.list] / 7中定义为:
缩小转化是隐式转化
从浮点类型到整数类型,或
从
long double
到double
或float
,或从double
到float
,除非来源是常量表达式和实际值转换后的值在可以表示的值范围内 (即使它无法准确表示),或从整数类型或未范围的枚举类型到浮点类型,除了源 是一个常量表达式,转换后的实际值将适合目标类型 转换回原始类型时生成原始值,或
从整数类型或未范围的枚举类型到不能代表所有的整数类型 原始类型的值,除非源是一个常量表达式,其值在积分之后 促销活动将适合目标类型。
答案 1 :(得分:1)
第一个是复制初始化,第二个是列表初始化。
但是,通常复制初始化较少使用。因为,如果你是通过传递用户定义类型的对象来实现的,那么它只会导致bitcopy&因此,如果用户定义的类使用指针,则可能无法产生预期的结果。
答案 2 :(得分:0)
虽然对int
的现有答复是完整的,但我痛苦地发现,在某些情况下,()
和{}
之间还有其他区别初始化。
关键字是{}
是初始化列表。
其中一种情况是,使用std::string
的{{1}}个副本对count
进行了初始化:
char
会将std::string stars(5, '*')
初始化为stars
,但是
*****
将被读取为std::string stars{5, '*'}
,并将星号初始化为std::string stars(char(5), '*')
(以隐藏字符开头)。