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

探究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( 42 73 ); ← 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 *   this int  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,  42 73 ); ← 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( 42 73 );
 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(),将程序无法防止编译器消除这个临时量。

你可能感兴趣的:(探究C++编译器返回值优化)