我看VC2005中的返回值优化

一直以来,我都认为C++中,返回大对象或多个对象就是一场恶梦:额外的开销太多,对于原生类型还可以承受,但对大对象来说,就严重地影响效率。所以STL的容器再方便,那也仅限于操作int,double这些类型,换作是操作自定义类型,一不小心就会掉近了陷阱。不过这方面还好,有boost的指针类型对象容器可以利用,是一种比较好的解决方案。另一方面,返回值的处理也不能都像Blitz::Array操作那样,可以用表达式模板来幽雅地解决。大多数情况下,对“返回值”的操作都不像Blitz::Array那样是线性的。

今天查到了一篇关于返回值优化的文章,发现是MSDN的翻译版,看得我那是一个恶心~~于是找到了原版,细细读了一下。其实内容比较简单,只是翻译这种工作实在不适合用机器做。以下就简单总结一下我的收获。

  • 返回值为何要优化(原文说得太隐晦了)

看这个代码:

#include  < stdio.h >
class  RVO
{
public:
       
            RVO()
{printf("I am in constructor ");}
            RVO (
const RVO& c_RVO) {printf ("I am in copy constructor ");}
            
~RVO(){printf ("I am in destructor ");}
            
int mem_var;       
}
;
RVO MyMethod (
int  i)
{
            RVO rvo;                
//一个构造
            rvo.mem_var = i;
            
return (rvo);            //构造生成一个临时的隐藏变量,传递给函数外部,之后rvo自己析构
}

int  main()
{
            RVO rvo;               
//一个构造
            rvo=MyMethod(5); //返回了一个RVO对象,但还有一个operator = 操作(这也是降低效率的,但不在此文讨论的范围)
}


以上代码中,进行了三次构造(其中有一个是拷贝构造),三次折构。如果你发现不了解何来的三次构造,可以看以下的伪码:

// 原函数
RVO MyMethod ( int  i)
{
            RVO rvo;
            rvo.mem_var 
= i;
            
return (rvo);
}

//  以下是按编译器的理解写的伪码
MyMethod ([ out ] RVO  &  _hiddenArg,    int  i)
{
            RVO rvo;
            rvo.mem_var 
= i;
            _hiddenArg.RVO(rvo); 
//临时隐藏变量的构造
           return;
           rvo.
~RVO();
          
// 隐藏变量在函数外析构
}

在VC2005中,编译器虽然按以上思路把一个函数的的返回值当作临时隐藏变量来处理,但通过编译优化选项,可以消除隐藏变量。对于以上代码来说,开启了优化参数(o2)之后,就只有二个构造函数调用,具体来说,就是return rvo语句中的rvo直接当作了返回值。

可以看到,使用返回值优化后,虽然效率高了一些,但函数的行为变了:原来需要的拷贝构造函数和它的析构函数都没了。这就是所谓的 Optimization Side Effects 。多数情况下,这种优化是合适的,我们可以放心优化。

然而,返回值优化却不是总能使用的。有一些情况会阻止编译器进行这种优化。

  • 函数使用exeception

不解释了,这好理解。

  • 不对命名的函数对象(Different Named Objects)

这个情况是说,函数有可能有多个分支,最终导致有多个不同位置的return语句。对于此项优化,要求所有return返回的对象的名字都是一致的。如写成下面的情况,就不行:

RVO MyMethod ( int  i)
{
            RVO rvo;
            rvo.mem_var 
= i;
      
if (rvo.mem_var == 10)
         
return (RVO());
            
return (rvo); 
}

PS:中文翻译真是太次了,MSDN上的Named Object,实际上是强调这些对象的名字都是一样的,是同一对象;而Path则指的程序分支。

  • EH Restriction 

不知道怎么翻译,但这一条实际上是说,当函数有多个返回语句时,而且返回的对象类型中有显式的析构函数声明时,能不优化。这一条,比上一条更加严格。看

RVO MyMethod ( int  i)
{
            RVO rvo;
           
if (i==10)
         
return (rvo);
      rvo.mem_var 
= i;
            
return (rvo); 
}

已经满足了前一条。但却还是不能优化,因为RVO中有显式的析构函数。如果省略掉RVO析构函数的话,就可以优化了。但还有下面另一种写法:

RVO MyMethod ( int  i)
{
            RVO rvo;
      
if (i!=10)
         rvo.mem_var 
= i;
      
return(rvo);  
}

 优化的关键,就是只在一个地方返回。

  • 嵌入的汇编代码中引用了返回对象

这条比较简单,就不上代码了。

总结:虽然VC2005中的Named Return Value Optimization已经为我们减少了返回对象带来的一些额外负担,但这不是完全无条件的。需要记住的一点就是,只在函数的一个地方写return。另一方面,这种优化还不够,因为只减少了隐藏变量的构造与析构(还有一点“单边影响”),新的优化办法还需要探求。

原文的地址是: http://msdn2.microsoft.com/en-us/library/ms364057(VS.80).aspx

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值