20 协助完成返还值最优(RVO)

一个返回对象的函数很难有较高的效率,因为值传递返回会导致对象的构造和析构的成本,这种调用不可避免。

考虑rational(有理数)类的成员函数operator*:

class Rational
{
public:
	Rational(int numerator = 0,int denominator = 1);
	...
	int numerator() const;
	int denominator() const;
};

const Rational operator*(const Rational& lhs,const Rational& rhs);

不用看operator*的代码,就知道它肯定返回一个对象,因为它返回的是两个任意数字的计算结果。这些结果是任意数字,operator*不能避免建立新对象并返回。

有时候人们返回的指针,从而导致滑稽的结果:

const Rational* operator*(const Rational& lhs,const Rational& rhs);

Rational a= 10;
Rational b(1,2);
Rational c = *(a*b);	//看起来很奇怪

它会引发一个问题,调用者应该删除函数对象返回的指针,并且通常导致资源泄露。

其他一些开发人员会返回引用,看上去合理,但是却是危险的:

const Rational& operator*(const Rational& lhs,const Rational& rhs);

Rational a= 10;
Rational b(1,2);
Rational c = a*b;	//看起来合理

但是函数的实现却是危险的:

const Rational& operator*(const Rational& lhs,const Rational& rhs)
{
	Rational result(lhs.numerator()*rhs.numerator()),
				lhs.denominator()*rhs.denominator());
	
	return result;
}

函数返回的是引用,当函数返回的时候,其指向的对象却不存在了。

对于一些函数(operator*之类的)必须返回其对象。

我们可以采用某种特殊写法来撰写函数,使他在返回对象时,能够让编译器消除临时对象的成本。

技术是返回所谓的constructor arguments以取代对象。

你可以这么做:

const Rational operator*(const Rational& lhs,const Rational& rhs)
{
	return Rational (lhs.numerator()*rhs.numerator()),
				lhs.denominator()*rhs.denominator());
}

此时返回的是临时对象,C++允许编译器将临时对象优化,使它们不存在,于是你如此这样调用

operator*:
Rational a = 10;
Rational b(1,2);
Rational c = a*b;

你的编译器得以消除“operator*内的临时对象”以及“被operator*返回的临时对象”。它们可以将return表达式所定义的对象构造于c的内存内。这样你调用operator*的临时对象总成本为0,也就是没有任何临时对象被产出来。取而代之,你只需付出一个constructor(用于产生c)。你可以将此函数声明为inline,以消除调用operator*所花费的额外开销。

真正的编译器都有做这些优化工作,此特殊的优化行为——利用函数的return点消除一个局部临时对象(并可能用函数端调用的某个对象取代),专属名称叫return value optimization(返回值最优化)。

猜你喜欢

转载自blog.csdn.net/weixin_28712713/article/details/81279573
20)
$20
20