零初始化初始化列表中的数组成员

时间:2014-12-09 15:01:42

标签: c++ initialization initialization-list array-initialization

我有一个带有数组成员的类,我想将其初始化为全零。

class X
{
private:
    int m_array[10];
};

对于局部变量,有一种直接的零初始化方法(参见here):

int myArray[10] = {};

此外,类成员m_array显然需要初始化,因为默认初始化的int将只留下随机垃圾,如here所述。

但是,我可以看到两种方法为成员数组执行此操作:

括号:

public:
    X()
    : m_array()
    {}

括号:

public:
    X()
    : m_array{}
    {}

两者都正确吗?这两者在C ++ 11中有什么区别吗?

3 个答案:

答案 0 :(得分:15)

使用()初始化任何成员执行值初始化。

使用{}的默认构造函数初始化任何类类型都会执行值初始化。

使用{}初始化任何其他聚合类型(包括数组)执行列表初始化,相当于使用{}初始化每个聚合成员。

使用{}初始化任何引用类型构造一个临时对象,该对象从{}初始化,并将引用绑定到该临时对象。

使用{}初始化任何其他类型执行值初始化。

因此,对于几乎所有类型,{}的初始化将产生与值初始化相同的结果。您不能拥有引用数组,因此这些不能成为例外。 可能能够在没有默认构造函数的情况下构造聚合类类型的数组,但编译器对确切的规则不一致。但是回到你的问题,所有这些极端情况对你来说并不重要:对于你特定的数组元素类型,它们具有完全相同的效果。

答案 1 :(得分:12)

初始化的类型可能有点繁琐,但在这种情况下它是微不足道的。为:

public:
    X()
    : m_array()
    {}

由于括号之间的表达式列表为空,因此会发生值初始化。同样适用于:

public:
    X()
    : m_array{}
    {}
由于 brace-init-list 为空,

列表初始化发生,随后进行值初始化。


为了给出更全面的答案,让我们来看看N4140的§8.5。

  
      
  1. 如果没有为对象指定初始值设定项,则对象为   默认初始化。使用自动或自动存储对象时   获得动态存储持续时间,该对象具有不确定   值,如果没有为对象执行初始化,那么   对象保留不确定的值,直到替换该值   (5.17)。
  2.   

这个不确定值就是你所说的垃圾值。

  
      
  1. 零初始化 T类型的对象或引用意味着:

         

    - 如果T是数组类型,则每个元素都是零初始化

  2.   
  3. value-initialize T类型的对象意味着:

         

    - 如果T是(可能是cv限定的)类类型...那么该对象是默认初始化的; ...

         

    - 如果T是数组类型,则每个元素都是值初始化的;

         

    - 否则,该对象为零初始化。

  4.   
  5. 初始值设定项的语义如下。 ...    - 如果初始化程序是(非括号) braced-init-list ,则对象或引用是列表初始化的(8.5.4)。

         

    - 如果初始值设定项为(),则对象进行值初始化。

  6.   

到目前为止,很明显值初始化会使数组的每个元素为零,因为int不是类类型。但是我们还没有涉及列表初始化和聚合初始化,因为数组是聚合。

§8.5.4:

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

         

    - 如果T是聚合,则执行聚合初始化(8.5.1)。

  2.   

回到§8.5.1:

  
      
  1. 如果列表中的 initializer-clauses 少于那里   是聚合中的成员,然后每个成员不明确   初始化应从其 brace-or-equal-initializer 初始化   或者,如果没有 brace-or-equal-initializer ,则为空   初始化列表(8.5.4)。
  2.   

我们再次以§8.5.4结束:

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

         

    - 否则,如果初始化列表没有元素,则对象进行值初始化。

  2.   

由于遍历(草案)标准可能会让你失望,我推荐cppreference因为它打破了它非常好。

相关链接:

cppreference:

标准草案:

答案 2 :(得分:-1)

圆括号在C ++ 98中工作,并且正在调用零初始化,这就是你想要的。我在gcc 4.3上验证过。编辑:删除了关于C ++ 11的错误陈述。我还确认空括号使用clang 3.4和-std = c ++ 11执行空列表初始化。