c++中的RVO举例分析

  介绍

本篇内容主要讲解“C + +中的RVO举例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C + +中的RVO举例分析”吧!

前言

考虑存在这样一个类如HeavyObject,其拷贝赋值操作比较耗时,通常你在使用函数返回这个类的一个对象时会习惯使用哪一种方式?或者会根据具体场景选择某一种方式?

//, style  1
  HeavyObject  func (Args 参数);//style  2
  bool  func (HeavyObject * ptr,祝福;Args  param); 

上面的两种方式都能达到同样的目的,但直观上的使用体验的差别也是非常明显的:

风格1只需要一行代码,而风格2需要两行代码
//, style  1
  HeavyObject  obj =, func (params);//style  2
  HeavyObject  obj;
  func(及obj, params); 

但是,能达到同样的目的,消耗的成本却未必是一样的,这取决于多个因素,比如编译器支持的特性,c++语言标准的规范强制性,多团队多环境开发等等。

看起来风格2虽然使用时需要写两行代码,但函数内部的成本却是确定的,只会取决于你当前的编译器,外部即使采用不同的编译器进行函数调用,也并不会有多余的时间开销和稳定性问题。比如func内部使用铿锵声+ libc + +编译,外部调用的编译环境为gcc + gnustl或者vc++,除了函数调用开销,不用担心其它性能开销以及由于编译环境不同会崩溃问题。

因此这里我主要剖析一下风格1背后开发者需要关注的点。

RVO

RVO是返回值优化的缩写,即返回值优化,NRVO就是具名的返回值优化,为RVO的一个变种,此特性从c++ 11开始支持,也就是说C + + 98, c++ 03都是没有将此优化特性写到标准中的,不过少量编译器在开发过程中也会支持RVO优化(如IBM编译器吗?),比如微软是从Visual Studio 2010才开始支持的。

仍然以上述的HeavyObject类为例,为了更清晰的了解编译器的行为,这里实现了构造/析构及拷贝构造,赋值操作,右值构造函数,如下

 class  HeavyObject
  {
  公众:
  ,,,HeavyObject (), {, cout  & lt; & lt;,“构造函数\ n",,}
  ,,,~ HeavyObject (), {, cout  & lt; & lt;,“析构函数\ n",,}
  ,,,HeavyObject (HeavyObject  const&), {, cout  & lt; & lt;,“Copy 构造函数\ n",,}
  ,,,HeavyObject&,操作符=(HeavyObject  const&), {, cout  & lt; & lt;,“Assignment 操作员\ n";, return  *,,}
  ,,,HeavyObject (HeavyObject&,), {, cout  & lt; & lt;,“Move 构造函数\ n",,}
  私人:
  ,,,//,many  members 省略……
  };

编译环境:
AppleClang 10.0.1.10010046

<强> *第一种使用方式

 HeavyObject  func ()
  {
  ,,,return  HeavyObject ();
  }//调用
  HeavyObject  o =, func (); 

按照以往对c++的理解,HeavyObject类的构造析构顺序应该为

拷贝构造函数构造函数
析构函数

但析构函数是实际运行后的输出结果却为

构造函数析构函数

实际运行中少了一次拷贝构造和析构的开销,编译器帮助我们作了优化。

于是我反汇编了一下:

 0000000100000 f60  & lt; __Z4funcv>:
  ,,100000法郎:,,,,55岁,,,,,,,,,,,,,,,,,,,,,,,push , % rbp
  ,,100000 f61:,,,, 48岁,89年,e5 ,,,,,,,,,,,,,,,, mov ,,负责百分比、rbp百分比
  ,,100000 f64:,,,, 48岁,83年,ec  10,,,,,,,,,,,,,, sub ,, 0 x10,美元%负责
  ,,100000 f68:,,,, 48岁,89年,f8 ,,,,,,,,,,,,,,,, mov ,, % rdi, %伸展
  ,,100000 f6b:,,,, 48, 89, 45, f8 ,,,,,,,,,,,,, mov ,,, %伸展,0×8 (% rbp)
  ,,100000 f6f:,,,, e8  0 c  00, 00, 00,,,,,,,,,,, callq , 100000 f80  & lt; __ZN11HeavyObjectC1Ev>
  ,,100000 f74:,,,, 48, 8 b  45, f8 ,,,,,,,,,,,,, mov ,,, 0×8 (% rbp), %伸展
  ,,100000 f78:,,,, 48岁,83年,c4  10,,,,,,,,,,,,,, add ,, 0 x10,美元%负责
  ,,100000 f7c:,,,, 5 d ,,,,,,,,,,,,,,,,,,,,,, pop ,, % rbp
  ,,100000 f7d:,,,, c3 ,,,,,,,,,,,,,,,,,,,,,, retq ,,
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null
  null

c++中的RVO举例分析