【问题标题】:Are evaluations of expressions in member initialization sequenced with respect to each other?成员初始化中表达式的计算是否相互排序?
【发布时间】:2014-04-15 07:11:33
【问题描述】:

具体来说,假设我有:

struct X { X(int i) { cout << i; } };
int f() { cout << 'f'; return 0; }
int g() { cout << 'g'; return 1; }

struct Z {
    Z() : a(f()), b(g()) {}
    X a, b;
};

int main() { Z z; cout << '\n'; }

我知道成员的构造函数保证按照它们在struct 中定义的顺序被调用,所以0 将在1 之前打印。 但是如何评价他们的论点呢?是否保证:

f0g1

?或者,也许,

fg01

gf01

也是有效的输出?

对标准的参考表示赞赏。

【问题讨论】:

  • @ShafikYaghmour:我并不关心标准之间的差异。重要的是意图,很可能没有改变,只是变得更加清晰。
  • 有道理,据我所知,行为应该是相同的,并且正如您所建议的那样,C++11 只是明确表示。

标签: c++ constructor member language-lawyer


【解决方案1】:

C++11 draft standard 中,每个成员初始化器都是一个完整表达式,因此所有副作用都必须在评估下一个之前生效。

12.6.2 部分 初始化基和成员7 段说:

[...]每个 mem-initializer 执行的初始化构成一个完整的表达式。任何 mem-initializer 中的表达式被评估为执行初始化的完整表达式的一部分。[...]

1.9部分程序执行14段说:

与完整表达式关联的每个值计算和副作用都在与要评估的下一个完整表达式关联的每个值计算和副作用之前排序。

12.6.2部分的相关语法如下:

ctor-initializer:
   : mem-initializer-list
mem-initializer-list:
   mem-initializer ...opt
   mem-initializer , mem-initializer-list ...opt
[...]

Pre C++11 每个 mem-initializer 上的相同措辞都不存在,至少在最古老的草案标准中不存在 @987654322 @。但据我所知,我在 Are multiple mutations of the same variable within initializer lists undefined behavior pre C++11 中使用的相同逻辑也适用于这种情况,因此我们应该期待 C++11 之前的相同行为。

【讨论】:

    【解决方案2】:

    根据 C++ 标准

    每个 mem-initializer 执行的初始化构成一个 充分表达。 mem-initializer 中的任何表达式都被评估为 执行初始化的完整表达式的一部分

    所以首先会执行完整的表达式 a(f()),然后执行完整的表达式 b(g())。

    因为结果输出必须是

    f0g1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-07
      • 2022-01-11
      • 1970-01-01
      • 2011-07-14
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多