成员变量是否可用于初始化列表中的其他成员

Can member variables be used to initialize other members in an initialization list?

本文关键字:成员 其他 列表 用于 变量 是否 初始化      更新时间:2023-10-16

考虑以下(简化的)情况:

class Foo
{
private:
    int evenA;
    int evenB;
    int evenSum;
public:
    Foo(int a, int b) : evenA(a-(a%2)), evenB(b-(b%2)), evenSum(evenA+evenB)
    {
    }
};

当我像这样实例化 Foo 时:

Foo foo(1,3);
那么偶数A是0,偶数

B是2,但是偶数总和会初始化为2吗?

我在当前的平台 (iOS) 上尝试了这个,它似乎有效,但我不确定这段代码是否可移植。

感谢您的帮助!

这是定义明确且可移植的,1 但它可能容易出错。

成员按照它们在

类主体中声明的顺序进行初始化,而不是按照它们在初始化列表中列出的顺序进行初始化。 因此,如果更改类主体,此代码可能会静默失败(尽管许多编译器会发现这一点并发出警告)。


1. 从 C++ 标准中的 [class.base.init] :

在非委托构造函数中,初始化按以下顺序进行:

  • 首先,并且仅对于派生最多的类 (1.8) 的构造函数,虚拟基类初始化在 它们出现在基类有向无环图的深度优先从左到右遍历上的顺序, 其中"从左到右"是基类在派生类基说明符列表中的出现顺序。
  • 然后,直接基类按照它们出现在基说明符列表中的声明顺序进行初始化 (无论 mem 初始值设定项的顺序如何)。
  • 然后,按照非静态数据成员在类定义中声明的顺序初始化它们 (同样,无论 mem 初始值设定项的顺序如何)。
  • 最后,执行构造函数主体的复合语句。

(突出显示是我的。

然后,标准的这一部分继续给出使用成员变量初始化其他成员变量的示例。

是的,前提是它们已经被构建好了。 只是不要忘记构造顺序是声明中的顺序类定义,而不是初始值设定项在构造 函数。 而且编译器通常不会告诉你是否使用一个变量,在构造之前。 例如,在您的情况下,如果evenSum移动到类的顶部,则未定义行为(因为它的初始值设定项使用未初始化的成员),甚至尽管在构造函数中,您可以初始化evenA并以词法evenBevenSum之前.

成员

按照它们在类定义中声明的顺序进行初始化。只要初始值设定项列表遵循此顺序,它就应该没问题。

调用初始值设定项的顺序:初始化顺序

列表中成员初始值设定项的顺序无关紧要:初始化的实际顺序如下:

  1. 如果构造函数用于派生最多的类,则虚基将按照它们在基类声明的深度优先从左到右遍历中出现的顺序进行初始化(从左到右是指基说明符列表中的外观)
  2. 然后,直接碱基按从左到右的顺序初始化,因为它们出现在此类的基本说明符列表中
  3. 然后,非静态数据成员按照类定义中的声明顺序进行初始化。
  4. 最后,执行构造函数的主体

所以是的,你的示例将起作用,只要在evenSum之前声明evenAevenB

这也在 g++ 4.0.3(现在已经 6 岁了)上编译没有错误。

我相信这将在任何合理的最新编译器上编译良好。