[More Effective C++]条款22有关返回值优化的验证结果
(这里的验证结果是针对返回值优化的,其实和条款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有关返回值优化的验证结果的更多相关文章
- 返回值优化(RVO)
C++的函数中,如果返回值是一个对象,那么理论上它不可避免的会调用对象的构造函数和析构函数,从而导致一定的效率损耗.如下函数所示: A test() { A a; return a; } 在test函 ...
- 【M20】协助完成“返回值优化(RVO)”
1.方法返回对象,会导致临时对象的产生,这降低了效率,const Rational operator* (const Rational& lhs,Rational& rhs).有没有什 ...
- [转] C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- C++返回值优化RVO
返回值优化,是一种属于编译器的技术,它通过转换源代码和对象的创建来加快源代码的执行速度.RVO = return value optimization. 测试平台:STM32F103VG + Keil ...
- 转:C++中临时对象及返回值优化
http://www.cnblogs.com/xkfz007/articles/2506022.html 什么是临时对象? C++真正的临时对象是不可见的匿名对象,不会出现在你的源码中,但是程序在运行 ...
- C++返回值优化
返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用于返回,那么这个临时对象会消耗一个构造函数(C ...
- 一段小代码秒懂C++右值引用和RVO(返回值优化)的误区
关于C++右值引用的参考文档里面有明确提到,右值引用可以延长临时变量的周期.如: std::string&& r3 = s1 + s1; // okay: rvalue referen ...
- 返回值优化 RVO
<深度探索C++对象模型>-- 2.3 返回值的初始化 & 在编译器层面做优化
- Effective C++ -----条款22:将成员变量声明为private
切记将成员变量声明为private.这可赋予客户访问数据的一致性.可细微划分访问控制.允诺约束条件获得保证,并提供class作者以充分的实现弹性. protected并不比public更具有封装性.
随机推荐
- 一款简单的客户端安卓手机qq源码
给大家分享一款比较简单的安卓手机qq应用源码,效果非常不错,大家可以借鉴一下,希望大家会喜欢. 1.png (7.24 KB, 下载次数: 0) 02.png (68.52 KB, 下载次数: 0 ...
- Shell之sed命令
sed用于一次性处理所有的编辑任务,尤为高效,为用户节省了大量的时间,sed适用于以下三种场合: 1.编辑相对交互文本编辑器而言太大的文件: 2.编辑命令太复杂,在交互式文本编辑器中难以输入的情况: ...
- ViewPager控件的Demo
1.主视图 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:to ...
- 插件化—配置xml的辅助测试
1.xml文件,xml文件在res/xml目录下 <?xml version="1.0" encoding="utf-8"?> <infos& ...
- Nginx的500,502,504错误解决方法
Nginx的500,502,504错误解决方法 一.解决500错误: 1.500错误指的是服务器内部错误,也就是服务器遇到意外情况,而无法履行请求. 2.500错误一般有几种情况: (1)web脚本错 ...
- 深入windows的关机消息截获-从XP到Win7的变化
之前写了一个软件用于实验室的打卡提醒,其中一个重要的功能是在关机之前提醒当天晚上是否已经打卡.之前我是在WM_ENDSESSION中弹出一个模态对话框来提醒,在XP中基本工作正常,在Win7中大多数时 ...
- Handler不同线程间的通信
转http://www.iteye.com/problems/69457 Activity启动后点击一个界面按钮后会开启一个服务(暂定为padService),在padService中会启动一个线程( ...
- 如何解决office2007每次打开都要正在配置
前言 最近发现我的office2007每次打开的时候都要配置,超级烦人,而且还要等待很久,具体状况如下图: [caption id="attachment_1241" align= ...
- 操作PDF文档功能的相关开源项目探索——iTextSharp 和PDFBox
原文 操作PDF文档功能的相关开源项目探索——iTextSharp 和PDFBox 很久没自己写写心得日志与大家分享了,一方面是自己有点忙,一方面是自己有点懒,没有及时总结.因为实践是经验的来源,总结 ...
- Study notes for Latent Dirichlet Allocation
1. Topic Models Topic models are based upon the idea that documents are mixtures of topics, where a ...