C++ 赋值中的表达式求值

C++ 赋值中的表达式求值,c++,C++,我只是惊讶地看到,在GCC(4.3.2)上,赋值表达式的左侧可能比右侧先求值: int x,y; int& getX() { std::cout << "getX\n"; return x; } int& getY() { std::cout << "getY\n"; return y; } void test() { x = 3; y= 4; getX() = getY(); } 而在MSVC上,则使用相反的顺序。该标准对

我只是惊讶地看到,在GCC(4.3.2)上,赋值表达式的左侧可能比右侧先求值:

int x,y;

int& getX()
{
  std::cout << "getX\n";
  return x;
}

int& getY()
{
  std::cout << "getY\n";
  return y;
}

void test()
{
  x = 3; y= 4;
  getX() = getY();
}

而在MSVC上,则使用相反的顺序。该标准对此有何定义?

该标准未指定评估顺序,这意味着实现可以选择它想要的顺序。

是和否

本质上,该标准定义它是未指定的,并且只保证在调用函数时参数将准备就绪

编辑:更糟糕的是,表达式计算可能是交错的。参见示例

基本上,您应该记住,每当您有一个函数,并且
a=b
是一个函数调用:
operator=(a,b)
,那么函数参数的求值顺序是未指定的

GCC通常从右向左,但优化器可以决定,例如,从左向右有时会更快。它甚至可以在运行时更改,尽管出于实际原因,我从未见过这样的实现

编辑:

由于本标准不承诺特定的排序,甚至不承诺原子执行,因此以下声明:

test(foo() + bar(), fud());
可能导致以下4个调用序列:

  • 福,巴,福
  • 巴,福,福
  • 福、福、巴
  • 福,巴,福
当你理解“未指定”术语及其后果时,多少是“预期的”。。。但它也可能导致以下两个序列:

  • 福,福,巴
  • 巴,福,福
更令人惊讶的是。这是交错的

我在这里省略了
+
操作,该操作只能在计算
foo
bar
后执行,但可以在
fud
之前或之后执行


如果函数是纯函数,或者具有完全不相交的操作集,则不重要。有时会有一些令人惊讶的副作用,甚至可能导致内存泄漏…

赋值运算符
=
在C++98/03中不引入序列点,这一点很有名,或者在C++11中,两边的表达式彼此之间没有顺序。

运算符=的操作数求值顺序根据规范未指定:

除非另有说明,否则未指定单个运算符的操作数和单个表达式的子表达式的求值顺序以及副作用发生的顺序`


我不认为深入的解释与序列点有任何关系。我有:)例如:
I=++I+1未定义是序列点的结果。我看不出这个示例(在您的注释中)与主题之间有任何关系。表达式中未指定的操作数的求值顺序是一回事,调用未定义行为的另一个表达式是另一回事。@Nawaz:啊,我明白你的意思。实际上,序列点并不影响计算顺序,它们只影响表达式是否具有已定义的行为。我已经去掉了那个部分。
test(foo() + bar(), fud());