我昨天才刚刚了解到,为初始化列表项指定参数是可选的。但是,在这种情况下会发生什么规则?
在下面的示例中,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()) { }
};
答案 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点说:
一个对象,其初始化程序是一组空的括号,即(),应进行值初始化。
值初始化简单地说就是类的默认构造和非类型的零初始化。