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

新手上路,请多包涵

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

一:

 int abc = 7;

二:

 int abc {7};

这两种方法有什么区别?编译器对它们的处理方式是否不同,或者代码的执行方式是否存在差异?

原文由 techfun 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 455
2 个回答

精简版

通过 {..} 初始化是列表初始化,它禁止缩小转换。例如,如果 LLONG_MAXlong 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 然后说:

初始化的形式(使用括号或 = )通常是无关紧要的,但当初始化器或被初始化的实体具有类类型时,它就很重要;见下文。

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

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

同样,在这两个复制初始化之间:

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

即带有 {..} 的使用列表初始化。 {..} 被称为 _支撑初始化列表_。

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

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

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

缩小转换是隐式转换

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

  • from long double to double or float , or from double to float , except where the source is a constant表达式和转换后的实际值在可以表示的值范围内(即使不能准确表示),或者

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

  • 从整数类型或无作用域枚举类型到不能表示原始类型的所有值的整数类型,除非源是常量表达式,其值在整数提升后将适合目标类型。

原文由 dyp 发布,翻译遵循 CC BY-SA 3.0 许可协议

第一个是复制初始化,第二个是列表初始化。

但是,通常复制初始化较少使用。因为,如果您通过传递用户定义类型的对象来做到这一点,它只会导致位复制,因此如果用户定义的类使用指针,则可能不会产生预期的结果。

原文由 yuvi 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题