2

我指出了一个奇怪的 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
inc:i = 1
参见:i = 0 :1 预期
see2:i = 1
inc:i = 2
参见:i = 0 :2 预期
see2:i = 2
参见:i = 2

4

2 回答 2

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

请注意,行为是未指定的,但不是未定义的;它必须打印01。这是因为在调用inc;之前和之后获得了一个序列点。在 C++11 中,函数的执行相对于调用函数 (1.9p15) 中的评估是不确定的(但不是未排序的)。

于 2012-11-29T12:37:23.973 回答
0

这是正确的行为:标准没有指定执行给定语句的子表达式的顺序。在您的情况下,显然编译器首先执行所有子表达式,即在对任何调用进行评估之前i制作 的副本i以将它们传递给 的不同调用。see()inc()

于 2012-11-29T12:39:59.873 回答