C ++初始化列表中的默认值

时间:2013-01-10 13:57:55

标签: c++ standards initializer-list

我昨天才刚刚了解到,为初始化列表项指定参数是可选的。但是,在这种情况下会发生什么规则?

在下面的示例中,ptr是否会初始化为0,切换为false,而Bar默认构造?我想这个问题有点多余,因为如果未指定的参数值==未定义的行为,初始化列表中几乎没有意义。

我是否也可以指向C ++标准中指出初始化列表项没有给出参数的情况下的行为?

class Bar
{
    Bar() { }
};

class SomeClass;
class AnotherClass
{
public:
    SomeClass *ptr;
    bool toggle;
    Bar bar;

    AnotherClass() : ptr(), toggle(), bar() { }
    // as opposed to...
    // AnotherClass() : ptr(NULL), toggle(false), bar(Bar()) { }
};

3 个答案:

答案 0 :(得分:13)

是的,成员将分别初始化为零和默认构造的对象。

C ++ 11标准在12.6.2 / 7中指定了这种行为:

  

使用mem-initializer中的expression-list或braced-init-list   初始化指定的子对象(或者,如果是   委托构造函数,完成类对象)   用于直接初始化的8.5的初始化规则。

反过来,8.5 / 10读取:

  

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

第8.5 / 7段定义 value-initialized

  

对T类型的对象进行值初始化意味着:

     
      
  • 如果T是具有用户提供的构造函数的(可能是cv限定的)类类型(第9节)   (12.1),然后调用T的默认构造函数(和   如果T没有可访问的默认值,则初始化是错误的   构造函数);
  •   
  • 如果T是(可能是cv限定的)非联合类类型   没有用户提供的构造函数,那么对象就是   零初始化,如果T是隐式声明的默认构造函数   是非平凡的,那个构造函数被调用。
  •   
  • 如果T是数组类型,   然后每个元素都进行了值初始化;
  •   
  • 否则,对象是   初始化为零。
  •   

最后,8.5 / 5定义零初始化

  

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

     
      
  • 如果T是   标量类型(3.9),对象设置为值0(零),取为   一个整数常量表达式,转换为T;
  •   
  • 如果T是   (可能是cv-qualified)非联合类类型,每个非静态数据   成员和每个基类子对象都是零初始化和填充   被初始化为零位;
  •   
  • 如果T是(可能是cv合格的)联盟   类型,对象的第一个非静态命名数据成员为零 -   初始化和填充初始化为零位;
  •   
  • 如果T是   数组类型,每个元素都是零初始化;
  •   
  • 如果T是参考   类型,不执行初始化。
  •   

答案 1 :(得分:6)

  

在下面的示例中,ptr是否会被初始化为0,切换为false,以及Bar默认构造?

是。如果成员初始化程序出现在带有空括号的初始化程序列表中,则该成员值已初始化。这意味着数值类型将初始化为零,指向null,以及使用该构造函数的默认构造函数的类。

如果您根本没有将该成员包含在初始化列表中,那么它将默认初始化;在这种情况下。数字和指针类型将保持未初始化状态。

  

我是否也可以指向C ++标准中指出初始化列表项没有给出参数的情况下的行为?

C ++ 11 12.6.2 / 7规定规则与直接初始化相同。

C ++ 11 8.5 / 16指定如果初始化为(),则该对象是初始值。

C ++ 11 8.5 / 7定义了值初始化。

答案 2 :(得分:2)

初始化包含在[dcl.init](又名8.5)

第10点说:

  

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

值初始化简单地说就是类的默认构造和非类型的零初始化。