在C ++ 11中使用或不使用Curly括号的初始化差异

时间:2014-01-15 22:58:27

标签: c++11 initialization initializer-list

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

一:

int abc = 7;

两个

int abc {7};

这两种方法有什么区别?

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

3 个答案:

答案 0 :(得分:38)

短版

通过{..}进行初始化是列表初始化,禁止缩小转换次数。例如,如果LLONG_MAXlong 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 doubledoublefloat,或从doublefloat,除非来源是常量表达式和实际值转换后的值在可以表示的值范围内   (即使它无法准确表示),或

  •   
  • 从整数类型或未范围的枚举类型到浮点类型,除了源   是一个常量表达式,转换后的实际值将适合目标类型   转换回原始类型时生成原始值,或

  •   
  • 从整数类型或未范围的枚举类型到不能代表所有的整数类型   原始类型的值,除非源是一个常量表达式,其值在积分之后   促销活动将适合目标类型。

  •   

答案 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), '*')(以隐藏字符开头)。