我很惊讶地看到在 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();
}
调用 test() 输出
getX
getY
而在 MSVC 上,使用相反的顺序。标准对此有定义吗?
最佳答案
是也不是。
本质上,标准定义它是未指定的,只保证调用函数时参数准备就绪。
编辑:更糟糕的是,表达式求值可能会交错。请参阅示例。
基本上你应该只记得当你有一个函数时,a = b
是一个函数调用:operator=(a , b)
,然后在函数的参数被评估是未指定的。
GCC 通常从右到左,但优化器可以决定有时从左到右更快。它甚至可以在运行时更改,尽管出于实际原因我从未见过这样的实现。
编辑:
由于标准不 promise 特定的顺序甚至原子执行,因此以下声明:
test(foo() + bar(), fud());
可以导致以下 4 个调用序列:
- foo, bar, fud
- 吧,富,富
- fud, foo, bar
- fud, bar, foo
当您理解“未指定”术语及其后果时,这些或多或少是“预期的”......但它也可能导致以下 2 个序列:
- foo, fud, bar
- 酒吧、酒吧、酒吧
这更令人惊讶。这就是交织。
我在这里省略了+
操作,它只能在计算完foo
和bar
后执行,但可以执行在 fud
之前或之后。
如果函数是纯函数,或者具有完全不相交的操作集,则应该无关紧要。有时会有一些令人惊讶的副作用,甚至可能导致内存泄漏......
关于c++ - 赋值中的表达式评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8401425/