类型不匹配:一般情况是指当需要X类型的对象时提供的却是其它类型的对象。编译器需要以某种方式将提供的类型转换成要求的X类型。这一过程可能会产生临时对象。

按值传递:创建和销毁临时对象的代价是比较高的。倘若可以,我们应该按指针或者引用来传递对象以避免生成临时对象。

按值返回:如果编写的函数是按值返回对象(与引用或者指针相对),就很可能生成临时对象。

可以使用operator=()消除临时对象。

临时对象会以构造函数和析构函数的形式降低一半的性能

将构造函数声明为explicit,可以阻止编译器在幕后使用类型转换。

编译器常常创建临时对象来解决类型不匹配问题。通过函数重载可以避免这种情况

如果可能,应尽量避免使用对象拷贝。按引用传递和返回对象

在<op>可能是”+、-、*”或者”/”的地方,使用<op>=运算符可以消除临时对象

以下是测试代码(temporary_object.cpp):

#include "temporary_object.hpp"
#include <iostream>
#include <chrono>
#include <string>namespace temporary_object_ {// reference: 《提高C++性能的编程技术》:第五章:临时对象class Rational {friend Rational operator + (const Rational&, const Rational&);public:Rational(int a = 0, int b = 1) : m(a), n(b) {}
private:int m; // 分子int n; // 分母
};template<class T>
void g(T formalArg)
{}std::string f()
{std::string s;// ....return s;
}int test_temporary_object_1()
{
{ // 对象定义// 实例化Rational对象: 只有第一种初始化形式可以保证在编译器的执行过程中不产生临时对象。如果使用第2种或第3种形式,很可能产生临时对象,这依赖于编译器的实现。// 实际上,大多数编译器会通过优化省去临时对象,所以此处给出的3种初始化形式在效率上是等效的Rational r1(100); // 1Rational r2 = Rational(100); // 2Rational r3 = 100; // 3
}{ // 类型不匹配// Rational类没有声明接收整形参数的赋值运算符。然而编译器希望右边是Rational对象,这样可以按字节传给左边。所以,编译器必须想办法将我们提供的整形参数转换成Rational对象。幸运的是(对性能来说是不幸的),我们有构造函数知道如何根据一个整形参数创建Rational对象// 为了易于编程,编译器可以自由地转换类型。新的C++标准允许我们限制编译器禁止这种转换,可以通过声明构造函数为explicit来实现Rational r;r = 100;// 可以通过重载函数Rational::operator=()以接收整形参数,从而消除临时对象// Rational& operator = (int a) { m=a; n=1; return *this; }// 同样的原理可以推广到所有的函数调用。假设g()是一个接收string引用参数的函数调用// void g(const string& s) { ... }// 除非重载g()让它接收char*参数,否则调用g("message")会产生临时的string对象
}{ // 按值传递// 因为存在局部参数formalArg, g()的激活记录在栈上设置了占位符。编译器复制对象t的内容至g()位于栈上的formalArg中。对此,一种常用的做法是生成临时对象// 编译器将创建int类型的临时对象,并且使用t作为输入参数来复制构造它.然后临时对象作为实参传递给g()。该新创建的临时对象将按引用方式传递给g(). int t;g(t);
}{ // 按值返回// f()的返回值是string对象,编译器生成临时对象来存储返回值。然后存储f()返回值的临时对象赋给左边的对象pstd::string p;p = f();std::string s1 = "Hello";std::string s2 = "Wold";std::string s3_1 = s1 + s2; // 此处没有临时对象std::string s3_2;s3_2 = s1 + s2; // 此处产生临时对象
}{ // 使用op=()消除临时对象std::string s1, s2, s3;s1 = s2 + s3; // 此处产生临时对象s3 = s1; // operator=(),没有临时对象s3 += s2; // operator+=(),没有临时对象}
}{ // 两种方式计算s5std::string s1, s2, s3, s4, s5;// 1. 产生三个临时对象s5 = s1 + s2 + s3 + s4;// 2. 虽然"丑陋"但更高效,因为它不产生临时对象s5 = s1;s5 += s2;s5 += s3;s5 += s4;
}return 0;
}} // namespace temporary_object_

GitHub:https://github.com/fengbingchun/Messy_Test

提高C++性能的编程技术笔记:临时对象+测试代码相关推荐

  1. 提高C++性能的编程技术笔记:总结

    <提高C++性能的编程技术>这本书是2011年出版的,书中有些内容的介绍可能已经过时,已不再适用于现在的C++编程中,但大部分内容还是很有参考意义的. 这里是基于之前所有笔记的简单总结,笔 ...

  2. 提高C++性能的编程技术笔记:内联+测试代码

    内联类似于宏,在调用方法内部展开被调用方法,以此来代替方法的调用.一般来说表达内联意图的方式有两种:一种是在定义方法时添加内联保留字的前缀:另一种是在类的头部声明中定义方法. 虽然内联方法的调用方式和 ...

  3. 提高C++性能的编程技术笔记:虚函数、返回值优化+测试代码

    虚函数:在以下几个方面,虚函数可能会造成性能损失:构造函数必须初始化vptr(虚函数表):虚函数是通过指针间接调用的,所以必须先得到指向虚函数表的指针,然后再获得正确的函数偏移量:内联是在编译时决定的 ...

  4. 提高C++性能的编程技术笔记:构造函数和析构函数+测试代码

    对象的创建和销毁往往会造成性能的损失.在继承层次中,对象的创建将引起其先辈的创建.对象的销毁也是如此.其次,对象相关的开销与对象本身的派生链的长度和复杂性相关.所创建的对象(以及其后销毁的对象)的数量 ...

  5. 提高C++性能的编程技术笔记:设计优化/可扩展性/系统体系结构相关+测试代码

    1. 设计优化 我们可以粗略地将性能优化分为两种类型:编码优化和设计优化.编码优化定义为不需要完整理解要解决的问题或者应用程序的执行流程就能实施的优化.通过定义看出,编码优化用于局部代码,同时该过程不 ...

  6. 提高C++性能的编程技术笔记:编码优化+测试代码

    缓存:在现代处理器中,缓存经常与处理器中的数据缓存和指令缓存联系在一起.缓存主要用来存储使用频繁而且代价高昂的计算结果,这样就可以避免对这些结果的重复计算.如,循环内对常量表达式求值是一种常见的低性能 ...

  7. 提高C++性能的编程技术笔记:引用计数+测试代码

    引用计数(reference counting):基本思想是将销毁对象的职责从客户端代码转移到对象本身.对象跟踪记录自身当前被引用的数目,在引用计数达到零时自行销毁.换句话说,对象不再被使用时自行销毁 ...

  8. 提高C++性能的编程技术笔记:标准模板库+测试代码

    标准模板库(Standard Template Library, STL)是容器和通用算法的强效组合. 渐近复杂度:算法的渐近复杂度是对算法性能的近似估计.它是算法集到特定性能标准集的映射.如果需要对 ...

  9. 提高C++性能的编程技术笔记:多线程内存池+测试代码

    为了使多个线程并发地分配和释放内存,必须在分配器方法中添加互斥锁. 全局内存管理器(通过new()和delete()实现)是通用的,因此它的开销也非常大. 因为单线程内存管理器要比多线程内存管理器快的 ...

最新文章

  1. day9 线程与进程、队列
  2. 开发者欣慰:苹果表软件圣诞表现不错
  3. chrome 看每行代码的运行时间
  4. Python爬虫 解析库的使用
  5. 不要迷失在技术的海洋中【转】
  6. OpenGL 法线贴图 切线空间 整理
  7. 2022秋软工实践个人作业一
  8. tar 打包压缩与解压缩
  9. 八数码问题c语言,八数码问题的可解性
  10. PHP laravel系列之迷你博客搭建
  11. 【drawio笔记】新增字体
  12. 手游用户数据分析平台
  13. 干货丨1.3万字简述,PRD到底怎么写
  14. 英特尔向第11代vPro芯片添加了启用硬件的勒索软件检测
  15. html设置文字超过字数_CSS限制字数,超出部份显示点点点...
  16. 美国证券业托管和清算机构的发展与现状
  17. Java学习——类和对象(上)
  18. Java飞机大战小游戏练习
  19. FL Studio20.8完整版注册密钥下载有哪些新功能?
  20. python数字1 3怎么表示_Python3生成手写体数字方法

热门文章

  1. 70美元桌面电脑,树莓派400:键盘式集成开发板
  2. 解决全网90%以上的日期格式转换、日期序列等骚操作问题
  3. 设置WebStorm查看本地源码文件个人修改的历史记录快捷键Alt+Shift+H、Ctrl+Shift+H(通常用于调试bug,发现文件出问题需要回溯到若干天之前)
  4. 在温系统下制作马克系统引导安装镜像启动U盘安装马克OS
  5. 设置flashfxp选中ftp密码的时候显示出来看
  6. ue4中面部动画制作视频教程 Facial Animation More In Unreal Engine 4
  7. 递归/回溯:八皇后问题N-Queens
  8. f-fdisk做磁盘分区,起始扇区从2048块开始
  9. cuda cudnn pytorch版本对应关系
  10. 在Asp.Net MVC中设定site路径所对应的默认action