Benjamin

静以修身,俭以养德,非澹薄无以明志,非宁静无以致远。
随笔 - 397, 文章 - 0, 评论 - 196, 引用 - 0
数据加载中……

探究C++编译器返回值优化

返回值的开销
1 class Foo {  };
2  
3  Foo rbv();
4  
5  void yourCode()
6  {
7    Foo x = rbv(); ← the return-value of rbv() goes into x
8    
9  } 
上面代码中有多少个临时对象?在大多数的商用编译器中会对其进行优化,对上面的代码而言,编译器会做如下的优化:
1 Foo rbv()
2  {
3    
4    return Foo(4273); ← suppose Foo has a ctor Foo::Foo(int a, int b)
5  } 
编译器直接返回构造函数,实际上编译器是通过指针传递来达到这个目的。当在代码调用rbv(),编译器会产生一个指向本地对象(Foo(42,73)),这里说void*还不如说是Foo*。
 1 // Pseudo-code
 2  void rbv(void* put_result_here) ← Original C++ code: Foo rbv()
 3  {
 4    
 5  }
 6  
 7  // Pseudo-code
 8  void yourCode()
 9  {
10    struct Foo x;
11    rbv(&x); ← Original C++ code: Foo x = rbv()
12    
13  } 
这里编译器也把这个技巧用在构造函数中,如下面的例子所示;
1 // Pseudo-code
2  void Foo_ctor(Foo* thisint a, int b) ← Original C++ code: Foo::Foo(int a, int b)
3  {
4    
5  } 
事实上编译做了如下的工作:通过put_result_here来替代构造函数的this指针。
1  // Pseudo-code
2  void rbv(void* put_result_here) ← Original C++ code: Foo rbv()
3  {
4    
5    Foo_ctor((Foo*)put_result_here, 4273); ← Original C++ code: return Foo(42,73);
6    return;
7  } 
回到第一段代码,我们通过&x到rbv(),rbv()传递x到构造函数(像这个this指针),也就直接构造了x。这种返回值优化会使效率更高,即使不打开编译器的优化开关,因为它产生的代码比较少。
一些编译器还支持回返回值优化来返回本地(局部)变量,还提供所有的函数返回本地(局部)量,但不是所有的编译器都支持,例如下面的代码,g++支持而VC不支持。
 1 // Actual C++ code for rbv()
 2  Foo rbv()
 3  {
 4    
 5    Foo ans = Foo(4273);
 6    
 7    do_something_with(ans);
 8    
 9    return ans;
10  } 
这里编译器可能会产生一个本地(局部)变量ans,在return时拷贝构造ans通过指向put_result_here(的指针)并析构, 如果所有的函数都返回一个变量,那么编译器也支持构造ans通过put_result_here,如下所示
注意这里讨论的仅针对返回值,例如:如果Foo x=rbv()改成Foo x;x=rbv(),编译器会使用赋值操作符,除非提供默认的构造函数,其次这个赋值操作符和要和拷贝构造功能一样,在return时依然会有临时量产生,在使用赋值操作符拷贝它,再析构,这里的返回值优化也只是它(临时量)的一部分,但是如果改成Foo x,x = rbv(),将程序无法防止编译器消除这个临时量。

posted on 2010-05-08 19:21 Benjamin 阅读(1098) 评论(0)  编辑 收藏 引用 所属分类: C/C++


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理