我指出了一个奇怪的gcc行为: 当在同一指令上使用相同的变量时,并且当通过一个函数调用(通过引用或指针传递的变量)修改此变量时,不会修改同一指令的其他函数的变量更改。
这是正常的c ++行为还是boggus? 注意:未设置优化(-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
inc:i = 1
见:i = 0 :1预期
见2:i = 1
inc:i = 2
见:i = 0 :2预期
见2:i = 2
见:i = 2
答案 0 :(得分:2)
函数参数的评估顺序相互之间是不确定的。在这种情况下,gcc已选择将i
评估为早期传递给see
方法调用。
您的代码相当于:
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)中的求值,函数的执行是不确定的(但不是未序列的)。
答案 1 :(得分:0)
这是正确的行为:它不是由标准指定的,其中执行给定语句的子表达式。在您的情况下,显然编译器首先执行所有i
子表达式,即使i
的副本将它们传递给see()
,之前的之前的不同调用对inc()
的调用进行评估。