教你一招!C 编码优化之减少冗余拷贝或赋值
时间:2021-08-19 15:48:48
手机看文章
扫描二维码
随时随地手机看文章
[导读]临时变量目前遇到的一些产生临时变量的情况:函数实参、函数返回值、隐式类型转换、多余的拷贝。1.函数实参这点应该比较容易理解,函数参数,如果是实参传递的话,函数体里的修改并不会影响调用时传入的参数的值。那么函数体里操作的对象肯定是函数调用的过程中产生出来的。那么这种情况我们该怎么办...
临时变量
目前遇到的一些产生临时变量的情况:函数实参、函数返回值、隐式类型转换、多余的拷贝。1. 函数实参
这点应该比较容易理解,函数参数,如果是实参传递的话,函数体里的修改并不会影响调用时传入的参数的值。那么函数体里操作的对象肯定是函数调用的过程中产生出来的。那么这种情况我们该怎么办呢?如果callee
中确实要修改这个对象,但是 caller
又不想 callee
的修改影响到原来的值,那么这个临时变量就是必须的了,不需要也没办法避免。如果 callee
中根本没有修改这个对象,或者 callee
中这个参数本身就是 const
型的,那么将实参传递改为引用传递是个不错的选择(如果是基本类型的函数实参,则没有必要改为引用),可以减少一个临时变量而且不会带来任何损失。另外,推荐一个静态代码检查工具 cppcheck
,这个工具可以提示非基本类型的 const
实参改为引用。2. 函数返回值(返回对象)
函数返回值的情况比较复杂,因为编译器在这方面做了很多优化,编译器优化到何种程度我也没追根究底研究过。在没开任何优化选项的时候,gcc
也优化了一些简单的返回对象的情况。先看一段代码:A createA(int a)
{
A tmp;
tmp._a=a;
return tmp;
}
抛开所有优化不谈,函数中 createA
应该有一个构造操作(tmp
对象生成)和一个拷贝构造操作(tmp
对象返回时)。于是有些编译器尝试对函数返回时的拷贝构造进行优化:A createA(int a)
{
return A(a);
}
第一步可以被优化的拷贝构造就是上面的这种情况,即 RVO(return value optimization)
,这时候只能在函数返回一个未命名变量的时候进行优化。后来更进一步,可以在函数返回命名变量的时候也进行优化了,这就是 NRVO(named return value optimization)
。但是这时候,还有一种情况不能优化的情况是:如果 createA
函数内部不同的分支返回不同的对象。A createA(int a)
{
if(a%2==0)
{
A tmp;
tmp._a = 2;
return tmp;
}
else
{
A tmp;
tmp._a = 1;
return tmp;
}
}
比如上面这段代码,我在 gcc 3.4.5
的情况下测试,发现这种情况是不能优化的。但是也不排除 gcc
更高的版本或者某些在这方面做得更优秀的编译器已经可以优化这种情况。3. 隐式类型转换
代码中的一些类型的隐式转换也会产生临时变量,比如:class A
{
public:
A(int a=0):_a(a)
{
cout<<"constructor"< }
A(const A