(这里的验证结果是针对返回值优化的,其实和条款22本身所说的,考虑以操作符复合形式(op=)取代其独身形式(op),关系不大。书生注)

在[More Effective C++]条款22的最后,在返回值的返回方式上,大师Meyers推荐使用表达式[returnT(lhs)+=rhs;]这种使用匿名临时变量的方式,理由是“自古以来未具名对象总是比具名对象更容易被消除”,这种写法将更好地帮助编译器实现返回值优化(ReturnValue Optimization,简写RVO)。

针对上述说法,我在两款编译器上验证了一下(g++ 4.1.2,以下简称g++,及MS Visual C++2008,以下简称vc),结果并不如此。验证分三个阶段,具体结果如下。

(1)(不做加法计算,纯为RVO验证)

return T(lhs);

结果:g++和vc在不开编译优化选项的情况下,都进行了优化。即只会发生一次copy ctor。

(2)

return T(lhs) += rhs;

或者

T temp(lhs);

return temp += rhs;

结果:g++和vc即使开编译优化选项,也不会优化。即发生两次copyctor,分别在temp对象的构造时与return时。

(3)

T temp(lhs);

temp += rhs;

return temp;

结果:g++无论开不开编译优化选项,都会优化,也就是说针对具名对象temp做了优化。结果只发生一次copy ctor。

vc在不开编译优化选项的情况下,不会优化,打开优化选项的情况下(比如release模式下)会做优化。

乍看(2)的第一种写法和(3)的写法对比,会产生奇怪的错觉:(3)的具名对象都可以优化,为什么(2)的匿名临时对象反而不会优化?其实看看(2)的第二种写法就明白了,问题不在于具名对象还是匿名对象,问题在于return语句上附带的操作。

为了搞清楚这个问题,我们需要先来了解一下返回值优化的原理。根据C++标准规定,具名对象也可以经由RVO被优化去除,那么编译器如何优化呢?按照(3)的流程,正常情况下(不优化)应该这样做:

T temp(lhs);

 
//经由copyctor创建一个temp对象

temp += rhs; 
 
//在temp上进行操作

return temp; 
 
//返回temp,即经由copyctor将temp对象复制给外层的一个匿名临时对象(或某具名对象)

当编译器判断出函数的返回值是通过temp返回时,就可以将temp对象优化掉,而把在temp身上做的所有操作直接操做于外层的那个匿名临时变量身上,这样最后return所产生的copy操作就可以省掉了。

而在(2)的第二种写法中,temp就没办法被优化了,因为在return语句中,需要在temp对象上来做一个操作,编译器就只能老老实实的将temp构造出来,再以temp为参数做这个操作(调用相应函数),并将该函数返回结果再做一次copyctor复制出去。(2)的第一种写法原理相同。

这个验证结果带给我们的结论就是,如果你定义了一个专用于存储返回值的临时对象(具名或者匿名),那么在返回的时候不要再做多余的操作。另外,如果存在返回不同具名对象的多个路径,编译器将没办法在编译期确定哪个对象会被作为返回值返回,那么编译器也无法完成返回值优化。还有一件事情需要小心,那就是在某些编译器上(比如vc)根据编译选项的不同程序的行为会不同(除了少调用一次copyctor,还少一次临时变量的析构函数调用)。

当然,在优化这件事上,还需要慎重。为了完成返回值优化而硬写出难于理解的代码,甚至可能是效率更差的代码,就违反了我们的本意了。就像Meyers大师所说的,掌握好80-20原则,以及讲求证据的原则。

[More Effective C++]条款22有关返回值优化的验证结果的更多相关文章

  1. 返回值优化(RVO)

    C++的函数中,如果返回值是一个对象,那么理论上它不可避免的会调用对象的构造函数和析构函数,从而导致一定的效率损耗.如下函数所示: A test() { A a; return a; } 在test函 ...

  2. 【M20】协助完成“返回值优化(RVO)”

    1.方法返回对象,会导致临时对象的产生,这降低了效率,const Rational operator* (const Rational& lhs,Rational& rhs).有没有什 ...

  3. [转] C++中临时对象及返回值优化

    http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...

  4. C++返回值优化RVO

    返回值优化,是一种属于编译器的技术,它通过转换源代码和对象的创建来加快源代码的执行速度.RVO = return value optimization. 测试平台:STM32F103VG + Keil ...

  5. 转:C++中临时对象及返回值优化

    http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...

  6. C++返回值优化

    返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用于返回,那么这个临时对象会消耗一个构造函数(C ...

  7. 一段小代码秒懂C++右值引用和RVO(返回值优化)的误区

    关于C++右值引用的参考文档里面有明确提到,右值引用可以延长临时变量的周期.如: std::string&& r3 = s1 + s1; // okay: rvalue referen ...

  8. 返回值优化 RVO

    <深度探索C++对象模型>-- 2.3 返回值的初始化 & 在编译器层面做优化

  9. Effective C++ -----条款22:将成员变量声明为private

    切记将成员变量声明为private.这可赋予客户访问数据的一致性.可细微划分访问控制.允诺约束条件获得保证,并提供class作者以充分的实现弹性. protected并不比public更具有封装性.

随机推荐

  1. Android --Vibrator--震动服务

    1.取得震动服务的句柄 vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);或者vibrator = (Vibrator)getAppli ...

  2. UVa 725暴力求解

    A - Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Su Description   Writ ...

  3. 第四届蓝桥杯 c/c++真题

    第四届蓝桥杯 c/c++真题 <1>高斯日记 问题 大数学家高斯有个好习惯:无论如何都要记日记. 他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210 后来人们 ...

  4. BZOJ 1717: [Usaco2006 Dec]Milk Patterns 产奶的模式( 二分答案 + 后缀数组 )

    二分答案m, 后缀数组求出height数组后分组来判断. ------------------------------------------------------------ #include&l ...

  5. 轻量化ViewControllers,读文章做的总结

    推荐一个网站 http://objccn.io/ 我这两天才开始看 获益匪浅 看了第一篇文章 <更轻量的View Controllers>感觉写的不错 感觉作者 原文地址 http://o ...

  6. mysql字符串连接,重复等字符串函数总结

    mysql concat()函数 MySQL的concat函数可以连接一个或者多个字符串,如 select concat('10'); 输出 10 select concat('11','22','3 ...

  7. The Apache™ Batik Project

    Apache(tm) Batik SVG Toolkit - a Java-based toolkit for applications or applets that want to use ima ...

  8. 改动项目APP名字后,在真机执行报错:The provisioning profile specified in your build settings (“haotian”) has an AppI

    错误提醒:The provisioning profile specified in your build settings ("haotian") has an AppID of ...

  9. 在vc中使用xtremetoolkit界面库-----安装及环境配置

    近期想用一下xtremetoolkitPro界面库.网上的使用教程资源也不多,当中着实遇到了很多的困难,毕竟是首次使用. 首先当然是配置发开环境了: 我使用的是vc6.0+xtremetoolkitP ...

  10. 基于JSP+SERVLET的新闻发布系统(二)

    接下来讲解的是通过AJAX验证用户名是否已经添加 用户名: <input type="text" name="userName" id="use ...