假设我们有函数g:
int g(int x, int& y)
{
y = y + x++;
return x + y;
}
主要功能:
int main()
{
int x = 5;
int y = 2;
cout << g(g(x, y), y) << ' ';
cout << x << ' ' << y << endl;
}
它显示预期结果:
34 5 20
但是当我重写main时:
int main()
{
int x = 5;
int y = 2;
cout << g(g(x, y), y) << ' ' << x << ' ' << y << endl;
}
它打印
34 5 2
有人可以解释一下为什么在这两种情况下我们会有不同的行为吗?
答案 0 :(得分:0)
C ++ 17之前的版本:
cout << g(g(x, y), y) << ' ' << x << ' ' << y << endl;
x
和y
中存储的表达式后半部分的值可以分别在调用g
之前或之后或之间读取。
请注意,y
的参数列表中的表达式g
不会读取存储的值:y
是直接绑定到左值引用函数参数的左值,因此存在没有左值到右值转换。
对g
的调用具有以下行为,其中x
和y
指的是main
中的变量:
x = 5, y = 2
。g
后:x = 5, y = 7
(调用返回13
)。g
后:x = 5, y = 20
(调用返回34
)。因此,输出将以34 5
开头,但是最后一个数字可以是2
,7
或20
。这称为未指定行为。
Since C++17,<<
链的操作数从左到右排序;现在唯一可能的输出是34 5 20
。
注意:有些评论声称存在未定义的行为,但没有。在C ++ 03术语中,在函数调用的入口和出口处有一个序列点。函数y
的修改与y
中main
的读取被那些序列点之一隔开。在C ++ 11中,顺序是相同的,但是术语有所变化。参见point 11 here。