初始化的类型可能有点乏味,但在这种情况下它是微不足道的。为了:
public:
X()
: m_array()
{}
由于括号之间的表达式列表为空,因此会发生值初始化。同样适用于:
public:
X()
: m_array{}
{}
由于大括号初始化列表为空,因此发生列表初始化,随后进行值初始化。
为了给出更全面的答案,让我们看一下 N4140 的 §8.5。
- 如果没有为对象指定初始化程序,则该对象是默认初始化的。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,如果没有对该对象执行初始化,则该对象将保留一个不确定的值,直到该值被替换(5.17)。
这个不确定的值就是你所说的垃圾值。
对类型的对象或引用进行零初始化T
意味着:
— 如果 T 是数组类型,则每个元素都初始化为零
对类型对象进行值初始化T
意味着:
— 如果 T 是(可能是 cv 限定的)类类型……那么对象是默认初始化的;...
— 如果 T 是一个数组类型,那么每个元素都是值初始化的;
— 否则,对象被零初始化。
初始化器的语义如下。... - 如果初始化程序是(非括号)大括号初始化列表,则对象或引用是列表初始化的(8.5.4)。
— 如果初始值设定项是 (),则对象是值初始化的。
到目前为止,很明显值初始化将使数组的每个元素都为零,因为int
它不是类类型。但是我们还没有讨论列表初始化和聚合初始化,因为数组是一个聚合。
§8.5.4:
类型的对象或引用的列表初始化T
定义如下:
— 如果 T 是一个聚合,则执行聚合初始化 (8.5.1)。
回到§8.5.1:
- 如果列表中的初始化子句少于聚合中的成员,则每个未显式初始化的成员都应从其大括号或相等初始化器初始化
,或者,如果没有大括号或相等初始化器,从一个空的初始化列表(8.5.4)。
我们再次以 §8.5.4 结束:
类型的对象或引用的列表初始化T
定义如下:
— 否则,如果初始化列表没有元素,则对象被值初始化。
由于遍历(草案)标准会让你喘不过气来,我推荐cppreference因为它很好地分解了它。
相关链接:
cpp参考:
标准草案: