More Effective C++读书笔记---效率

来源:互联网 发布:我的千岁寒 知乎 编辑:程序博客网 时间:2024/06/06 23:50

效率
在用C++写出高效地程序之前,必须认识到C++本身绝对与你所遇到的任何性能上的总是无关。如果想写出一个高效的C++程序,你必须首先能写出一个高效的算法
十六、条款16--牢记80-20准则(80-20 rule)
1.80-20准备说的是大约定俗成20%的代码使用了80%的程序资源;大约20%的代码耗用了大约80%的运行时间;大约20%的代码使用了80%的内存;大约20%的代码执行80%的磁盘访问;80%的维护投入于大约20%的代码上,也就是说,软件的整体性能取决于代码组成中的一小部分
2.用profiler程序识别出令人讨厌的程序的20%部分。让它去直接的测试你感兴趣的资源
十七、条款17--考虑使用lazy evaluation(懒惰计算法)
1.从效率的观点来看,最佳的计算就是根本不计算。关键是要懒惰
2.当你使用了lazy evaluation后,采用此种方法的类将推迟计算工作直到系统需要这些计算的结果。如果不需要结果,将不用进行计算
3.引用计数
4.区别对待读取和写入:残酷的事实是我们如何判断是读取操作还是写入操作,通过使用lazy evluation和条款M30中讲述的proxy class,我们可以推迟做出是读操作还是写操作的决定
5.Lazy Fetching(懒惰提取)
6.Lazy Expression Evaluation(懒惰表达式的计算)
7.应用:能避免不需要的对象拷贝,通过使用operator[]区分出读操作,避免不需要的数据库读取操作,避免不需要的数字操作
十八、条款18--分期摊还期望的计算
1.这个条款的核心就是over-eager evaluation(过度热情计算法):在要求你做某些事情以前就完成它们
2.隐藏在over-eager evaluation后面的思想是如果你认为一个计算需要频繁进行,你就可以设计一个数据结构高效地处理这些计算需求,这样可以降低每次计算需求时的开销
3.采用over-eager最简单的办法就是caching(缓存)那些已经被计算出来而以后还有可能需要的值
4.caching是一种分摊期望的计算开销的方法,prefetching(预提取)是另一种方法。你可以把prefetch想像成购买大批商品而获得的折扣,以空间换效率
十九、条款19--理解临时对象的来源
1.在C++中,真正的临时对象是看不见的,它们不出现在源代码中。建立一个没有命名的非堆对象会产生临时对象。这种未命名的对象通常在两种条件下产生:为了使函数调用而进行隐式类型转换和函数返回对象时
2.仅当通过传值(by value)方式传递对象或传递常量引用(reference-to-const)参数时,才会发生这些类型转换。当传递一个非常量引用(reference-to-non-const)参数对象,就不会发生
3.C++语言禁止为非常量引用产生临时对象的原因:当程序员期望修改非临时对象时,对非常量引用进行的隐式类型转换却修改临时对象,这是不希望看到的
4.临时对象是有开销的,所以你应该尽可能地去除它们,然而更重要的是训练自己寻找可能建立临时对象的地方
二十、条款20--协助完成返回值优化
1.通过constructor argument而不是直接返回对象能让编译器消除临时对象的开销(这是编译器内部的优化)
二十一、条款21--通过重载避免隐式类型转换
1.在C++中有一条规则是每一人重载的operator必须带有一个用户自定义的参数
二十二、条款22--考虑用运算符的赋值形式(op=)取代其单独的形式(op)
1.从零开始实现operator+=和-=,而operator+和operator-则是通过调用前述的函数提供自己的功能。使用这种设计方法,只用维护operator的赋值形式就行。而且如果假设operator赋值形式在类的public接口里,这就不用让operator的单独形式成为类的友元
2.如果你不介意把所有的operator的单独形式放在全局域里,那就可以使用模板来替代单独形式的函数的编写:
template< typename T >
const T operator+( const T& lhs, const T& rhs )
{
 return T(lhs) += rhs;
}
const T operator-( const T& lhs, const T& rhs )
{
 return T(lhs) -= rhs;
}
3.这里指出三个效率方面的问题:一、总的来说operator的赋值形式比其单独形式效率更高,因为单独形式要返回一个新对象,从而在临时对象的构造和释放上有一些开销。operator的赋值形式把结果写到左边的参数里,因此不城要生成临时对象容纳operator的返回值;二、提供operator的赋值形式的同时也要提供其标准形式,允许类的客户端在便利与效率上做出折衷选择;三、涉及到operator单独形式的实现
二十三、条款23--考虑变更程序库
1.程序库的设计就是一个折衷的过程。理想的程序应该是短小的、快速的、强大的、灵活的、可扩展的、直观的、普遍适用的、具有良好的支持、没有使用约束、没有错误的。当然这也是不存在的。为尺寸和速度而进行优化的程序库一般不能被移值。具有大量功能的程序库不会具有直观性。没有错误的程序库在使用范围上会有限制。所以不同的设计者给这些条件赋予了不同的优先级。他们从而在设计中牺牲了不同的东西,因此一般两个提供相同功能的程序库却有着完全不同的性能特征
二十四、条款24--理解虚拟函数、多继承、虚基类和RTTI所需的代价

原创粉丝点击