我指出了一个奇怪的gcc行为:当同一指令使用相同的变量,并且当此变量由一个函数调用(通过引用或指针传递的变量)修改时,不会为同一指令的其他函数修改变量更改。
这是正常的 c++ 行为还是博古斯?
注: 未设置优化 (-O) 标志。
注意 2:这在 solaris CC 编译器中工作正常。
使用 gcc 4.5.3 演示(在 Linux 或 mingw/cygwin 上)
class C {
public:
const C & inc(int & i) const
{
++i;
cout << "inc: i = " << i << endl; return *this;
}
const C & see(int i) const
{
cout << "see: i = " << i << endl; return *this;
}
const C & see2(const int & i) const {
cout << "see2: i = " << i << endl; return *this; }
};
int main()
{
C c;
int i = 0;
c.see(i).inc(i).see(i).see2(i).inc(i).see(i).see2(i);
c.see(i);
return 0;
}
输出:
参见:i = 0
公司: i = 1
参见: i = 0 : 1 预期
参见 2: i = 1
公司: i = 2
参见: i = 0 : 2 预期
参见 2: i = 2
参见:i = 2
函数参数的求值顺序彼此不确定。 在这种情况下,gcc 选择提前评估传递给see
方法调用i
。
您的代码等效于:
class C {};
C &inc(C &c, int &i) { ++i; return c; }
C &see(C &c, int i) { std::cout << i << 'n'; return c; }
C c;
int i = 0;
see(inc(c, i), i);
see
参数的有效求值顺序为:
1. evaluate inc(...) to pass c to see(...)
2. evaluate i as an rvalue to pass to see(...)
1. evaluate i as an rvalue to pass to see(...)
2. evaluate inc(...) to pass c to see(...)
在前一种情况下,程序打印1
;在后者中,它打印0
。
请注意,行为是未指定的,但不是未定义的;它必须打印0
或1
。 这是因为序列点在调用inc
之前和之后获取;在 C++11 中,函数的执行相对于调用函数中的计算是不确定排序的(但不是未排序的)(1.9p15)。
这是正确的行为:它不是由标准指定的,给定语句的子表达式的执行顺序。显然,在您的情况下,编译器首先执行所有i
子表达式,即制作i
的副本以将它们传递给不同的see()
调用,然后再对inc()
调用进行评估。