成员初始值设定项列表中的求值顺序是什么?

问题描述 投票:0回答:4

我有一个带有一些参数的构造函数。我假设它们是按照列出的顺序初始化的,但在一种情况下,它们似乎是按相反的顺序初始化的,导致中止。当我颠倒参数时,程序停止中止。

下面是我正在使用的语法的示例。在这种情况下,需要在

a_
之前初始化
b_
。你能保证这个初始化顺序吗?

class A
{
  public:
    OtherClass a_;
    AnotherClass b_;

    A(OtherClass o, string x, int y)
      : a_(o)
      , b_(a_, x, y) {}
};
c++ gcc constructor initialization c++-faq
4个回答
343
投票

这取决于类中数据成员声明的顺序。因此

a_
将是您示例中的第一个,然后
b_
将是第二个。


226
投票

为了澄清,该标准在 class.base.init 下规定:

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

...

  • 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管内存初始化器的顺序)。

33
投票

现在的标准参考似乎是 12.6.2 第 13.3 节:

(13.3) — 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化 (同样无论内存初始化器的顺序如何)。


0
投票

查看其他答案,而无需了解其他成员初始化的详细信息,我建议阅读标准参考 12.6.2 第 13 节中的更多信息(感谢@Adam Getchell 提供链接):

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

(13.1) — 首先,且仅适用于 最底层派生类的构造函数 (1.8),
虚拟基类在中初始化 它们在基类有向无环图的深度优先从左到右遍历中出现的顺序, 其中“从左到右”是派生类中基类的出现顺序base-specifier-list

(13.2) — 然后,

直接基类按声明顺序初始化
它们出现在 base-specifier-list 中 (无论
mem-initializers 的顺序如何)。

(13.3) — 然后,

非静态数据成员被初始化
按照它们在类定义中声明的顺序 (同样无论
mem-initializers 的顺序如何)。

(13.4) — 最后,执行构造函数主体的

compound-statement

术语:

base-specifier-list

 - 派生类的基类列表。请参阅参考文献第 10 节。 
示例:
class A :
public virtual B, private C

mem-initializers

 - 班级成员的初始值设定项列表。 
示例:
A::A() :
number(1.0f), text("abc")
{ /* ... */}

compound-statement

 - {}
的块,即构造函数的主体。


就这样了,简单说一下顺序:

  1. 静态变量(参见stackoverflow问题C++静态变量初始化顺序,还有那个有趣的行为SIOF)。在单个翻译单元中,顺序遵循声明顺序,在不同的情况下,由编译器决定。
  2. 虚拟基类如 dfs 所示
  3. 直接基类按照派生列表中的顺序指定
  4. 非静态变量按声明(!不是初始化顺序)顺序
© www.soinside.com 2019 - 2024. All rights reserved.