我正在阅读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)。
我很想进入阅读标准的水平。有人能指出我正确的方向吗?
答案 0 :(得分:26)
您的引言确实涵盖了这一点:
如果初始化程序是(非括号内的) braced-init-list ,则对象或引用是列表初始化的(8.5.4)。
简化为8.5.4列表初始化。在这里,我已经解释/省略了与T x{}
:
对象或类型T的引用的列表初始化定义如下:
- 如果T是聚合,则执行聚合初始化(8.5.1)。
- 否则,如果初始化列表没有元素且T是具有默认构造函数的类类型,则该对象是值初始化的
- 否则,如果
的特化T
是std::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进行值初始化。