过早优化还是我疯了?

我最近在comp.lang.c ++中看到一段代码,它从函数返回一个静态整数的引用。 代码是这样的

int& f()
{
   static int x;
   x++;
   return x;
}

int main()
{
  f()+=1; //A
  f()=f()+1; //B
  std::cout<<f();

}

当我使用我的酷炫的Visual Studio调试器调试应用程序时,我看到只有一个调用语句A,并猜测我感到震惊。 我一直以为i+=1等于i=i+1所以f()+=1等于f()=f()+1 ,我会看到两个对f()调用,但我只看到一。 这是什么? 我是疯了还是我的调试器疯了,或者这是过早优化的结果?


这是标准关于+=和朋友所说的内容:

5.17-7:形式E1 op = E2的表达式的行为相当于E1 = E1 op E2,只是E1只计算一次。[...]

所以编译器就对了。


i+=1在功能上与i=i+1 。 实际上它的实现方式不同(基本上,它旨在利用CPU级别优化)。

但实际上,左侧仅评估一次。 它产生一个非const的l值,这就是读取该值所需的全部值,添加一个值并将其写回。

当您为自定义类型创建重载运算符时,这更为明显。 operator+=修改this实例。 operator+返回一个新的实例。 通常推荐(在C ++中)编写oop + = first,然后根据它编写op +。

(注意这仅适用于C ++;在C#中, op+=与您的假设完全相同:只是op+的简写,并且您不能创建自己的op + =,它会自动为Op +创建)


你的想法是合乎逻辑但不正确的。

i += 1;
// This is logically equivalent to:
i = i + 1;

但是在逻辑上相同和相同并不相同。
代码应该看起来像这样:

int& x = f();
x += x;
// Now you can use logical equivalence.
int& x= f();
x = x + 1;

编译器不会进行两个函数调用,除非您明确地将两个函数调用放入代码中。 如果你的函数有副作用(就像你这样做),并且编译器开始增加额外的难以看到隐式调用,这将是很难真正理解代码的流程,从而使维护非常困难。

链接地址: http://www.djcxy.com/p/39633.html

上一篇: Premature optimization or am I crazy?

下一篇: Am I understanding premature optimization correctly?