T v {}初始化

zac*_*zac 19 c++ language-lawyer uniform-initialization c++11

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

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

是值初始化或默认初始化(自动存储).它确实说得非常清楚:

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).

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

M.M*_*M.M 26

您的报价确实涵盖了这一点:

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

跳过8.5.4列表初始化.在这里,我已经解释/省略了一些与以下情况无关的要点T x{}:

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

  • 如果T是聚合,则执行聚合初始化(8.5.1).
  • 否则,如果初始化程序列表没有元素且T是具有默认构造函数的类类型,则对象将进行值初始化
  • 否则,如果Tstd::initializer_list<E> [...] 的专业化
  • 否则,[如果列表不为空且与构造函数匹配]
  • 否则,[如果列表只有一个元素]
  • 否则,[if T是引用类型]
  • 否则,如果初始化列表没有元素,则对象进行值初始化.
  • 否则,该计划是不正确的.

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

对于第二点"T是具有默认构造函数的类类型",它是值初始化的,这意味着调用默认构造函数.

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

回到聚合初始化案例,在8.5.1/7中有:

如果列表中的initializer-clause少于聚合中的成员,那么未明确初始化的每个成员都应从其brace-or-equal-initializer初始化,或者如果没有bra-or-equal-initializer,从空的初始化列表(8.5.4).

所述支架或-等于初始值设定是指在类定义内联提供了一种初始化.如果不存在那么它被初始化,好像该成员已被初始化{}(因此,这个逻辑被递归地应用于每个聚合成员).

例如,

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

然后T x {};导致a被初始化,好像它是int a{};,这是值初始化,因为int是一个原始类型.


小智 8

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

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

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

和:

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

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

[...]

  • 否则,如果braced-init-list没有元素,则T是值初始化的.