过早优化还是我疯了?
我最近在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