返回值优化
- 前言
这一章主要讲的是返回值优化,这个优化通常会交给编译器实现,用于加快源代码执行,通过对源代码进行转化并消除对象实现的。 - 按返回值构造
以下的例子主要是complex实现复数的类:
class Complex {
friend Complex operator+(const Complex&, const Complex&);
public:
Complex(double a = 0.0, double b = 0.0)
: real(a)
, imag(i)
{
}
Complex(const Complex& c)
: real(c.real)
, imag(c.imag)
{
}
Complex& operator=(const Complex&);
~Complex(){}
private:
double real;
double imag;
};
这个类的操作符函数,比如加法的函数如下:
Complex& operator+(const Complex& a, const Complex& b)
{
Complex retVal;
retVal.real = a.real + b.real;
retVal.imag = a.imag + b.imag;
return retVal;
}
以上可以看出,加法的结果是返回值返回的。实际上编译器内部会进行操作a=b+c这样的结果,a会被编译器临时构造出来,b和c都是引用传递,因此两个参数的函数会被临时创建为三个参数的函数。同样的调用的时候也会发生变化,需要传递三个参数,这个就是返回值优化的步骤之一。
3. 返回值优化
上述的代码可以看出返回值的优化可以做到在函数中通过加参数,避免retVal在返回时被创建的开销。但是这种方法也会有局限性,比如多个返回值的场景;再比如有些编译器会在直接返回表达式时不采用优化方法。
void Complex_Add(const Complex& _tempResult,
const Complex& a,
const Complex& b)
{
_tempResult.Complex::Complex();
_tempResult.real = a.real + b.real;
_tempResult.real = a.imag + b.imag;
return;
}
- 计算性构造函数
编译器无法进行优化时,开发者可以使用计算性构造函数推一把。比如在返回值的时候推迟创建,在最后一刻返回时利用构造函数创建一个临时返回值返回。这样的弊端就是需要自己引入另一个构造。这样加法还好,如果需要添加多种运算那一只增加构造函数也挺费劲,因此在性能问题面前需要自己判断哪个更重要。 - 总结
返回值优化主要通过消除局部对象的创建
RVO也就是说的返回值临时创建的方法取决于编译器是否有这样的策略
如果一直没有RVO,也可以尝试使用计算性构造函数来推动编译器使用RVO