T v {}初始化

时间:2014-09-21 21:46:00

标签: c++ c++11 language-lawyer uniform-initialization

我正在阅读C ++ 11标准,但无法弄清楚是否

T x{};

是值初始化或默认初始化(自动存储)。 非常明确地说:

  

10一个对象,其初始化器是一组空的括号,即(),应进行值初始化。

那个

  

11如果没有为对象指定初始化程序,则该对象是默认初始化的;

但我能找到关于T x{};的所有内容是:

  

在表格T x(a)中发生的初始化;   T x {a};   以及在新表达式(5.3.4)中,static_cast表达式(5.2.9),函数表示法类型转换(5.2.3)以及基本和成员初始化器(12.6.2)称为直接初始化。

  

如果初始化程序是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4)。

我很想进入阅读标准的水平。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:26)

您的引言确实涵盖了这一点:

  

如果初始化程序是(非括号内的) braced-init-list ,则对象或引用是列表初始化的(8.5.4)。

简化为8.5.4列表初始化。在这里,我已经解释/省略了与T x{}

的情况无关的一些观点
  

对象或类型T的引用的列表初始化定义如下:

     
      
  • 如果T是聚合,则执行聚合初始化(8.5.1)。
  •   
  • 否则,如果初始化列表没有元素且T是具有默认构造函数的类类型,则该对象是值初始化的
  •   
  • 否则,如果Tstd::initializer_list<E> [...]
  • 的特化   
  • 否则,[如果列表不为空且与构造函数匹配]
  •   
  • 否则,[如果列表包含单个元素]
  •   
  • 否则,[如果T是参考类型]
  •   
  • 否则,如果初始化列表没有元素,则对象将进行值初始化。
  •   
  • 否则,该程序格式不正确。
  •   

第一点,聚合初始化也在C ++ 03中;在这种情况下,T x{};T x = {};相同。

对于第二点“T是具有默认构造函数的类类型”,它是 value-initialized ,这意味着调用默认构造函数。

如果T是基本类型,则应用倒数第二个点,并再次值初始化

回到聚合初始化的情况,在8.5.1 / 7中有:

  

如果列表中的初始化子句比集合中的成员少,那么未明确初始化的每个成员都应从其括号或等于初始值初始化,或者,如果没有大括号或等于-initializer,来自空的初始化列表(8.5.4)。

brace-or-equal-initializer 是指在类定义中内联提供的初始值设定项。如果不存在那么它被初始化,好像该成员已经用{}初始化(因此,这个逻辑被递归地应用于每个聚合成员)。

例如,

struct T
{
     int a;
};

然后T x {};导致a被初始化,就像它是int a{};一样,这是值初始化,因为int是基本类型。

答案 1 :(得分:8)

虽然Matt McNabb已经介绍了这一点,但我会补充一点,如果您在浏览标准时遇到问题,那么查看cppreference并不会有什么坏处。他们关于list initialization的部分很好地打破了它。

基本上,就像你的标准引语所说,T x{};指的是:

  

使用大括号括起来的列表初始化命名变量   表达式或嵌套列表( braced-init-list )。

  

类型T对象的列表初始化的效果是:

     
      
  • 如果braced-init-list为空且T是具有默认构造函数的类类型,则执行值初始化。
  •   
     

[...]

     
      
  • 否则,如果braced-init-list没有元素,则对T进行值初始化。
  •