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

tec*_*fun 28 initialization initializer-list c++11

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

一:

int abc = 7;
Run Code Online (Sandbox Code Playgroud)

二:

int abc {7};
Run Code Online (Sandbox Code Playgroud)

这两种方法有什么区别?

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

dyp*_*dyp 39

精简版

初始化通过{..}列表初始化,禁止缩小转换.例如,if LLONG_MAX是a的最大值long long int,并且您int不能表示:

int x = LLONG_MAX;  // probably accepted with a warning
int x {LLONG_MAX};  // error
Run Code Online (Sandbox Code Playgroud)

同理:

long long y = /*something*/;

int x = y;  // accepted, maybe with a warning
int x {y};  // error
Run Code Online (Sandbox Code Playgroud)

长版

表单的初始化

T x = a;
Run Code Online (Sandbox Code Playgroud)

复制初始化 ; 任何一种形式的初始化

T x(a);
T x{a};
Run Code Online (Sandbox Code Playgroud)

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

[dcl.init]/14然后说:

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

因此对于非类类型,初始化的形式无关紧要.但是,这两个直接初始化之间存在差异:

T x(a);  // 1
T x{a};  // 2
Run Code Online (Sandbox Code Playgroud)

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

T x = a;    // 1
T x = {a};  // 2
Run Code Online (Sandbox Code Playgroud)

即,{..}使用列表初始化的那些.它{..}被称为braced-init-list.

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

int x (a);
int x {a};
Run Code Online (Sandbox Code Playgroud)

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

缩小转换是隐式转换

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

  • long doubledoublefloat,或者从doublefloat,除非源是一个常量表达式和转换后的实际值是可以表示的值的范围(即使它不能被精确地表示)内,或

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

  • 从整数类型或未范围的枚举类型到不能表示原始类型的所有值的整数类型,除非源是一个常量表达式,其整数提升后的值将适合目标类型.

  • @moooeeeep这不是一种单独的初始化.它使用表达式`std :: random_device {}`构造一个`std :: random_device`类型的临时表,然后调用该对象的重载`operator()`,就像`std :: random_device rd; rd()`会的.`random_device`有一个`operator()`,它调用RNG并返回一个(伪)随机数,参见http://en.cppreference.com/w/cpp/numeric/random/random_device/operator() (4认同)
  • +1令人遗憾的是,选择了错误的答案. (3认同)
  • 这种同时使用括号和大括号的初始化怎么样:`std::random_device{}()` ? (2认同)