在成员初始值设定项列表中递增会产生未定义的行为吗?

Does incrementing in a member initializer list generate undefined behavior?

这会导致未定义的行为吗?具体来说,初始化列表中的递增以及如何对其进行评估。

class Wrinkle {
public:
    Wrinkle(int i) : a(++i), b(++i), x(++i) {}
private:
    int a;
    int x;
    int b;
};

成员声明和初始化列表之间的顺序差异是有意为之的,因为这是一个可以准确展示差异的示例,所以请暂时忽略它。

C++17 标准包含示例 almost exactly the same as in the question:

struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
  D(int);
  B1 b;
  const int c;
};

D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ }
D d(10);

后面是注释:

[ Note: The initialization performed by each mem-initializer constitutes a full-expression (4.6). Any expression in a mem-initializer is evaluated as part of the full-expression that performs the initialization. — end note ]

在 link 之后,第 4.6 节告诉我们 definitions of "full-expression" is

之一

... a mem-initializer, including the constituent expressions of the initializer,

短语 "including constituent expressions of the initiailizer" 强烈建议我上面的代码是合法的,因为 ++i 的副作用将在继续下一个初始化程序之前完成。不过,这只是我对标准的解读,我很乐意听从任何比我有更多标准经验的人。

(还值得注意的是,成员的初始化将按照它们在 class 中声明的顺序进行,而不是按照它们在成员初始化列表中出现的顺序进行)。

这不会生成未定义的行为,因为:

[class.base.init]#7

[ Note: 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]

5. A full-expression is

  • [...]
  • an init-declarator or a mem-initializer, including the constituent expressions of the initializer,

9. 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.


但要注意:

[class.base.init]#13

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).

因此您的代码将有效地将 i + 1 分配给 a,将 i + 2 分配给 x,将 i + 3 分配给 b