读书笔记——C++性能优化指南

文章目录

C++性能优化指南

注:以下内容仅限于个人收获总结记录参考
总领:尽量去使用C++所拥有的特性,能提升大部分的性能

  1. x = x + y和x += y有性能区别,+=的性能提升大大高于前者。
  2. 如果知道容器所需要的大小,可以提前reserve设置,这样不会出现可能的内存重新分配。较大提升。
  3. 消除拷贝构造函数的调用,这种最常见的就是std::move和const &xxx了,也会提升。
  4. 引用变量是作为指针实现的,所以如果需要使用引用里面的元素,务必使用迭代器来访问,这样不用解引用访问。
  5. 移除对返回值的复制。可以直接传入一个引用,然后在引用上改,最后不用返回值,临时变量什么的。
  6. 当程序有及其严格的性能需求时,还是需要用C的字符数组来代替std::string,虽然更加难用了,但是性能的提升到顶了,*ptr++ = str[i]的使用顺序是ptr++再用*ptr去进行赋值。而且还需要手动在末尾进行+"/0"设置。
  7. 始终记得,优化是有度的,是灵活的,要充分考虑接口的安全性,工作量的增加,后续的代码错误等等
  8. 我们看到,游戏在debug阶段,非常卡,但是release非常流畅。不仅仅是打开了内联,还有不少release的优化。
  9. 直接对字符串的+和-对比,append,substr等string类函数的效率往往大于其粗暴的处理。
  10. earse的使用,标准库的算法使用都是非常不错的。但是注意vector,map等容器的使用earse需要用返回的值赋给迭代器,不然就是造成迭代器不确定。itor = vec.earse(itor),当然map也可以用map.earse(itor++),运用到了后缀++的特性,有一个临时变量铺垫,但是我还是推荐前者。
  11. 不要混合使用高效的算法,那会使算法时间和复杂度提升。而且,查找算法只有在数据量大的前提下才能有明显的差距,10几个数据看不出什么东西。
  12. 我们比较的实体,实际上比较的是实体中的某个成员变量值,不是具体的实体比较,实体比较返回的应该永远是false。
  13. **最近项目上稍微新一点的技术没有使用,所以这里记录一下优化非常不错的智能指针。使用方法大约是:std::unique_ptr<类> 指针名(指向的目标),std::shared_ptr p_forExample(new string(“niconico”),使用API创建就是make_shared和make_unique注意后者需要C++14。创建的api可以同时用来保存被指向的类实例和其引用计数。std::shared_ptr p = std::make_shared(“hello”)**且这个操作是属于比较昂贵的原子操作。如果有主引用,使用unique_ptr
  14. 初始化和赋值不是一个概念,我们要尽可能用{}初始化,不用new直接初始化(new带有java等其他语言的特性)。
  15. 在性能极度匮乏的情况下,是不是能用array替换vector。
  16. 预分配容器容量(这个感觉还行)
  17. 循环外创建动态变量,综合考虑赋值,构造,拷贝,移动等的性能消耗对比。
  18. 一般函数的返回值,都是调用的复制构造函数进行复制出来(如果是自定义类)
  19. 提到了do-white循环和for循环的差异,以前的编译器上性能还是do-white性能好。
  20. 递减的循环性能比递增的性能好。(为什么?看汇编,会发现递减少一条指令)
  21. 现代的编译器多会将循环中不变的变量提出后替我们重写循环。要能敏锐的识别出循环中隐藏的函数调用,构造函数,赋值函数,运算符函数,退出作用域时的析构函数,vector等数据结构插入元素时的复制/移动构造函数。
  22. 不要盲目的去相信一些书上的性能的提升,只有真正的自己性能测试过,才能算。
  23. 函数的调用过程,代码执行中,遇到函数,先保存当前的执行位置,控制权交给函数体,直到return交回控制权,很高效的讲函数插入到指令执行流中。
  24. 函数调用中的开销:

函数开销
最后,栈帧弹出。
25. 成员调用是通过this指针调用的,这个this指针必须写到调用栈上的内存中,或者保存的寄存器中。函数指针有其对应的开销,比如解引用来获取函数体的地址。
26. debug和release版本之间的差别,可能就是内联函数是否有开启。所以inline的性能提升非常大。
27. 虚函数是非常高效的机制,但是要记得,virtual加上重写override,一定要实现,不要空着,结构要舒服。
28. 编译器不会进行我们的数学优化,也不会快速转换常量。
29. >>位移运算符的确能提升性能。但我个人不习惯
30. float和double的快慢,还和编译器有关。
31. 虚函数调用通过索引虚函数表得到,这个开销总是常数时间。
32.
在这里插入图片描述
上面的是不正常的(反模式。。是不良的编程),下面的是更多实际中不成熟面向对象代码。
33. 可能世界上根本没有符合标准的实现,C++的标准库也是一样,所以不同实现的STL,也依旧带有不同BUG,虽然他很少。
34. 对于STL来说,性能反而是其次的,特性的覆盖更加重要。
35. 还是那句话,最快的性能,解题速度,往往是单独用来解决这个问题的方法。
36. 对STL的优化实际上是有上限的,如果要突破这个上限,我们就只能修改这个一般性,调用原生函数,移植性换取运行速度。
37. 在黑暗的源代码,库上安全的修改的办法,就是新增一个接口和实现。
38. 继承的层次最好不要超过3层,函数的嵌套调用不能超过3层。
39. 标准库里面有find,find_if和binary_search二分查找。不过这个二分查找返回bool,不返回这个值。
40. vector的直接赋值操作性能很高,因为一步到位。vector只有在往乱七八糟的地方插入元素,空间不够的时候才会有动作。直接完全的insert也高,从一个容器全部复制insert(xx.end(),xx.begin(),xx.end())。仅次于前者。
41. 指针的解引用获取值,消耗的性能比xx.at()和xx[]慢。如果我们写一个循环,去一个个把值复制进去,性能差距比第40条慢6倍。
42. 如果在插入之前知道能总共需要的容量,reserve到需要的大小,再push_back,性能会很好。千万不要在开头插入元素,想办法把第一和最后一个元素的值对调也行,不然性能差距有3000倍之大。
43. deque属于典型的先进先出容器,跟vector类似,不过操作时间比例跟vector对比没有亮点,包括迭代,查找,排序都慢30%左右。对于deque,下标的访问反而比迭代器慢。
44. list的开销对比vector也差多了,而且不支持下标,只能迭代器,find查找。不过对比deque还是有优势的,而且性能与forward_list性能差不多。
45. map的插入,最好带有一个指示的位置迭代器。vector迭代器遍历的效率目前无人能敌。
46. map的插入,先找到想要插入的点,用find,再插,比直接插要快。
47. 散列表的空间申请比较的昂贵。查找性能比有序的vector快1.7倍。但是空间浪费,如果函数不好,负载不行,非常差。
48. 目前,经验丰富的并发开发C++开发人员一直使用的原生线程库或是基本线程服务功能的POSIX线程库(这是一个跨平台解决方案)。C++没有进程概念,只有线程。
49. 单核时代,并发是通过竞争条件,时间分割实现的。
50. STL中对C++的并发支持实际上还是简陋,因为其必须对全平台保持一致性,按照计划,C++17会对并发有突飞猛进的支持。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++性能优化 指南(强列推荐) chm版 Part I: Everything But the Code Chapter 1. Optimizing: What Is It All About? Performance Footprint Summary Chapter 2. Creating a New System System Requirements System Design Issues The Development Process Data Processing Methods Summary Chapter 3. Modifying an Existing System Identifying What to Modify Beginning Your Optimization Analyzing Target Areas Performing the Optimizations Summary Part II: Getting Our Hands Dirty Chapter 4. Tools and Languages Tools You Cannot Do Without Optimizing with Help from the Compiler The Language for the Job Summary Chapter 5. Measuring Time and Complexity The Marriage of Theory and Practice System Influences Summary Chapter 6. The Standard C/C++ Variables Variable Base Types Grouping Base Types Summary Chapter 7. Basic Programming Statements Selectors Loops Summary Chapter 8. Functions Invoking Functions Passing Data to Functions Early Returns Functions as Class Methods Summary Chapter 9. Efficient Memory Management Memory Fragmentation Memory Management Resizable Data Structures Summary Chapter 10. Blocks of Data Comparing Blocks of Data The Theory of Sorting Data Sorting Techniques Summary Chapter 11. Storage Structures Arrays Linked Lists Hash Tables Binary Trees Red/Black Trees Summary Chapter 12. Optimizing IO Efficient Screen Output Efficient Binary File IO Efficient Text File IO Summary Chapter 13. Optimizing Your Code Further Arithmetic Operations Operating System–Based Optimizations Summary Part III: Tips and Pitfalls Chapter 14. Tips Tricks Preparing for the Future Chapter 15. Pitfalls Algorithmic Pitfalls Typos that Compile Other Pitfalls
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值