初始化列表中的依赖项

Dependencies in Initialization Lists

本文关键字:依赖 列表 初始化      更新时间:2023-10-16

此行为是否定义良好?

class Foo
{
    int A, B;
    public:
    Foo(int Bar): B(Bar), A(B + 123)
    {
    }
};
int main()
{
    Foo MyFoo(0);
    return 0;
}

不,它是未定义的。 A将首先初始化(它在类定义中是第一个(,它使用未初始化的B

成员按照它们在类定义中出现的顺序进行初始化,而不考虑它们在初始化列表中的顺序。实际上,将成员定义顺序与初始化列表顺序不匹配是一种不好的做法。

如果您的 Foo 实例恰好具有静态持续时间(如在 Foo f(0); int main(){} 中(,则行为是明确定义的。具有静态持续时间的对象在发生任何其他初始化之前初始化为零;在这种情况下,运行构造函数时,AB 将为 0。但是,在那之后,行为是相同的:首先A然后B,给A一个值123,B一个值Bar(仍然很丑(。

不,初始化顺序由类本身中的声明顺序定义。

从C++标准12.6.2 [class.base.init] p5

初始化应按以下顺序进行:
— 首先,并且仅对于下面描述的最派生类的构造函数,虚拟基类应按照它们在基类的有向无环图的深度优先从左到右遍历上的顺序进行初始化,其中"从左到右"是基类名称在派生类基说明符列表中的出现顺序。
— 然后,直接基类应按照它们出现在基本说明符列表中的声明顺序进行初始化(无论 mem 初始值设定项的顺序如何(。
— 然后,非静态数据成员应按照它们在类定义中声明的顺序进行初始化(同样,无论 mem 初始值设定项的顺序如何(。
— 最后,执行构造函数的主体。
[注:宣布令的授权是为了确保以与初始化相反的顺序销毁基对象和成员子对象。

初始化是按照声明中出现的顺序完成的,而不是按照在构造函数中编写它的顺序完成的。

看看这个问题,有点相似:初始值设定项列表 *参数* 计算顺序