我读过这篇文章:未定义的行为和序列点,但我不知道,是否是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;
}
Run Code Online (Sandbox Code Playgroud)
我希望这样的输出(或基于评估顺序的输出的一些排列):
x: 0
x: 1
x: 2
res: 3
Run Code Online (Sandbox Code Playgroud)
gcc-4.7.1和clang-3.0给了我这样的输出,但是当我用msvc-2010编译这个例子时,我得到了输出:
x: 0
x: 0
x: 0
res: 3
Run Code Online (Sandbox Code Playgroud)
你能告诉我一些关于这种行为的信息.
Ser*_* K. 10
参数评估的顺序a + b + c是特定于编译器的.因此,调用的顺序x++将是特定于编译器的,并且在其上的中继将是未定义的行为.
使用x++或++x在此类表达式中通常表示编码标准不良.最好避免它并简化表达.
在这个问题C++中编译器和评估的参数顺序你可以在C++中找到关于参数评估顺序的讨论.
以下是对C++评估顺序的解释,其中引用了C++标准:http://en.cppreference.com/w/cpp/language/eval_order
PS Bjarne Stroustrup在"The C++ Programming Language"第3版第6.2.2节中明确表示.他还给出了一个理由:
在没有对表达式评估顺序的限制的情况下,可以生成更好的代码.
这是未定义的行为,因为后增量之间没有序列点x.您无法分辨哪个+将首先评估,您无法分辨哪个op(x++)将首先构建,并且您无法确定x++将执行哪个顺序.这是未定义的,只是不要编写这样的代码.