构造函数的初始化列表中的函数调用是否已排序?

Are functions calls in a constructor's initializer-list sequenced?

考虑:

int f () {
    static int i = 0;
    return i++;
}

struct Test {
    int a, b;
    Test () : a(f()), b(f()) {}
};

Test t;

我知道 ab 之前初始化,因为它们在 struct 中的声明顺序。

我也知道 g(f(), f()) 中对 f 的两次调用是无序的。

所以我想知道是否保证t.a == 0t.b == 1

I know that a is initialized before b due to the order of their declaration in the struct.

没错。

我对该约束的解释是 a 不能在 b 之前初始化,除非初始化表达式的求值在 b 初始化之前完成。

我在标准中没有看到任何关于对用于初始化非静态成员的表达式求值排序的内容。但是,我在 C++11 标准 (12.6.2/12) 中看到以下示例:

Names in the expression-list or braced-init-list of a mem-initializer are evaluated in the scope of the constructor for which the mem-initializer is specified. [ Example:

class X {
  int a;
  int b;
  int i;
  int j;
  public:
  const int& r;
  X(int i): r(a), b(i), i(i), j(this->i) { }
};

除非 this->i 的计算在 i 初始化后排序,否则这将无效。

So I am wondering if it is guaranteed that t.a == 0 and t.b == 1?

只要 a 在 class 声明中出现在 b 之前并且在 [=12= 的初始化之间没有其他调用 f() ] 和 b。 Class 成员按照它们在 class 中声明的顺序进行初始化。 [class.base.init]/11:

In a non-delegating constructor, initialization proceeds in the following order: [...]

  • Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).

因此,由于 ab 之前,因此当构造函数初始化 a 时,它将第一次调用 f(),然后在它初始化 b.

我们也知道成员初始化器之间有一个序列点,因为 [class.base.init]/7:

[...]The initialization performed by each mem-initializer constitutes a full-expression. Any expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization.

告诉我们每个初始化器都是一个完整的表达式,每个完整的表达式都是按顺序排列的:[intro.execution]/14

Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.