5

我读过这篇文章:未定义的行为和序列点,但我不知道它是否是 UB。

考虑以下示例:

#include <iostream>
class op {
public:
  explicit op(int x) {
    std::cout << "x:   " << x << std::endl;
  }

  op & operator + (const op & /* other */) {
    return *this;
  }
};

int main(int /* argc */, char * /* argv */ []) {
  int x = 0;
  op o = op(x++) + op(x++) + op(x++);

  std::cout << "res: " << x << std::endl;

  return 0;
}

我期望这样的输出(或基于评估顺序的一些输出排列):

x:   0
x:   1
x:   2
res: 3

gcc-4.7.1 和 clang-3.0 给了我这样的输出,但是当我用 msvc-2010 编译这个例子时,我得到了输出:

x:   0
x:   0
x:   0
res: 3

你能给我一些关于这种行为的信息吗?

4

2 回答 2

10

参数评估的顺序a + b + c是特定于编译器的。因此,调用的顺序x++将是特定于编译器的,并且对其进行中继将是未定义的行为。

在这样的表达方式中使用x++++x通常是编码标准不佳的标志。最好避免它并简化您的表达方式。

在这个问题Compilers and argument order of evaluation in C++ 中,您可以找到关于 C++ 中参数评估顺序的讨论。

以下是 C++ 评估顺序的解释以及对 C++ 标准的引用: http: //en.cppreference.com/w/cpp/language/eval_order

PS Bjarne Stroustrup 在“C++ 编程语言”第 3 版第 6.2.2 节中明确说明了这一点。他还给出了一个理由:

在没有表达式求值顺序限制的情况下可以生成更好的代码。

(来自https://stackoverflow.com/a/2934909/1065190

于 2012-11-12T12:41:54.713 回答
9

这是未定义的行为,因为 . 的后增量之间没有序列点x。你不知道哪个+会先评估,你不知道哪个op(x++)会先被构造,你不知道x++会以什么顺序执行。它是未定义的,只是不要写那样的代码。

于 2012-11-12T12:38:00.253 回答