效率:条款20 协助完成“返回值优化(RVO)”

函数如果返回对象,对效率狂而言是一个严重的挫折,因为以by-value方式返回对象,背后隐藏的constructor和destructor都将无法消除。

有的人会返回指针,于是导致下列这种拙劣的语法形式:

const Rational* operator*(const Rational* lhs,const Rational* rhs)
{
    return new Rational(lhs*rhs);
}
她会引出一个重要的问题,导致内存泄漏的问题。
另一些程序员可能会返回reference,于是到处一个危险的做法:

const Rational& operator*(const Rational* lhs,const Rational* rhs)
{
    Rational result(lhs.a*rhs.a,lhs.b*rhs.b);
    return result;
}
此函数返回一个reference,指向一个不再存在的对象,更明确的说,它返回一个reference指向局部对象result,但该局部对象在返回时自动被销毁了,导致返回一个reference指向一个不存在的对象。
总的来说:如果函数一定得以by-value方式返回一个对象,你绝对无法消除之。这是一场错误的战争从效率的眼光来看,你不应该在乎函数返回了一个对象,你应该在乎的是那个对象的成本几何。你需要做的事女里找出某种方法来降低返回对象的成本,而不是想尽办法消除对象本身。

我们可以用某种特殊写法来撰写函数,使它在返回对象时,能够让编译器消除临时对象的成本。我们的伎俩是:返回所谓的constructor arguments(构造函数参数)一取代对象。如:

函数一:const Rational operator*(const Rational* lhs,const Rational* rhs)
{
    Rational temp(lhs.a*rhs.a,lhs.b*rhs.b);
    return temp;
}<pre name="code" class="cpp">函数二:const Rational& operator*(const Rational* lhs,const Rational* rhs)
{
 
    return Rational(<span style="font-family: Arial, Helvetica, sans-serif;">lhs.a*rhs.a,lhs.b*rhs.b);</span>
}
以上两者的区别在于函数一多创建了一个临时对象。而函数二仅仅创建了一个临时对象。函数二具体的做法是以constructor arguments取代局部对象,当作返回值。

 如果你这样调用时: 

Rational a=10;
Rational b(1,2);
Rational c=a*b;
C++则会允许编译器将临时对象优化使它们不存在。如上面公式所写,比的编译器会消除operator*内的临时对象及被operator*返回的临时对象。它们可以将return表达式所定义的对象构造于c的内存内。如果编译器这样做,你调用operator*时的临时对象总成本为0也就是说没有任何临时对象需要被产生出来,取而代之的是,您只需要付出一个constructor(用以产生c)的代价。你无法做的比这更好了,因为c是一个命名对象,而命名对象是不能被消除的。

结论:此特殊的优化行为有一个专属的名词:return value optimization。利用函数的return点消除一个局部临时对象(并可能利用函数调用端的某个对象取代),“拥有专属名称”说明它拥有很广泛。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值