这是未指定(未定义)的行为吗?

时间:2012-11-12 12:36:04

标签: c++

我已经阅读了这篇文章:Undefined behavior and sequence points,但我无法确定它是否是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

您能否告诉我一些有关此行为的信息。

2 个答案:

答案 0 :(得分: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

P.S。 Bjarne Stroustrup在“The C ++ Programming Language”第3版第6.2.2节中明确表示。他还给出了一个理由:

  

在没有对表达式评估顺序的限制的情况下,可以生成更好的代码。

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

答案 1 :(得分:9)

这是未定义的行为,因为x的后增量之间没有序列点。您无法确定哪个+将首先评估,您无法确定将首先构建哪个op(x++),并且您无法确定将执行x++的顺序。这是未定义的,只是不要写那样的代码。