《More Effective C++》读书笔记-效率
来源:互联网 发布:教育过程最优化 编辑:程序博客网 时间:2024/05/19 05:01
条款16-18省略。
19、了解临时对象的来源
临时对象产生的两种条件:
1、为了使函数成功调用而进行隐式类型转换时。
2、函数返回对象时。
临时对象是有开销的,因此要尽可能去消除它们,然而更重要的是训练自己寻找可能建立临时对象的地方,在任何时候只要见到常量引用参数,就存在建立临时对象而绑定在参数上的可能性,在任何时候只要见到函数返回对象,就会有一个临时对象被建立(以后被释放)。
20、协助完成返回值优化
略过。
21、通过重载避免隐式类型转换
隐式类型转换将产生临时对象,从而带来额外的系统开销。
解决办法是使用重载,以避免隐式类型转换。要注意的一点是在C++中有一条规则是每一个重载的operator必须带有一个用户定义类型的参数(这条规定是有道理的,如果没有的话,程序员将能改变预定义的操作,这样做肯定把程序引入混乱的境地)。
另外,牢记8020规则,没有必要实现大量的重载函数,除非有理由确信程序使用重载函数后整体效率会有显著提高。
class UPint { public: UPint(); UPint(int value); .... } //重载operator+(const UPint& lhs,const UPint& rhs)const UPint operator+(const UPint& lhs,const UPint& rhs); UPint u1,u2; UPint u3 = u1 + u2;//都是UPint对象,利用上述重载operator+即可//以下两种情形也可成功,为什么?因为以下语句执行了隐式类型转换,产生了//临时对象,并将整数10转换为UPint。UPint u4 = 10+u2;UPint u4 = u2+10;
编译器来执行此类隐式转换,很方便,但是此类转换会产生临时对象,从而产生我们不想要的运行成本。我们并不想进行隐式类型转换,仅仅想要能够对UPint和int进行加法,可以利用重载函数,每个函数拥有不能的参数。如下列所示:
const UPint operator+(cosnt UPint& lhs,int rhs); const UPint operator+(int lhs,const UPint& rhs);
22、考虑以操作符复合形式(op=)取代其独身形式(op)
要确保操作符的复合形式和其独身形式之间的自然关系能够存在,一个好方法就是以复合形式为基础来实现独身形式。
Rational& operator+=(const Rational& rhs);//(1)const Ratinal operator+(const Rational& lhs,const Rational& rhs) {//(2) return Rational(lhs)+=rhs; }
此例中operator+=是从头做起的,而operator+是调用前者以供应它们所需的机能。如果采用这种设计,那么这些操作符之中就只有复合形式才需要维护。 主要有以下好处:
1、一般而言,复合操作符比独身版本效率高,因为独身版本通常必须返回一个新对象,故必须要负担一个临时对象的构造和析构成本。至于复合版本则是直接将结果写入其左端自变量,所以不需要产生一个临时对象来放置返回值。
2、允许客户在效率和便利之间作取舍。
Rational a,b,c,d,result; //(1)独身版本:便利。用到三个临时对象。result = a+b+c+d; //(2)复合版本:效率。都不需要临时对象。 result=a; result+=b; result+=c; result+=d;
前者较易撰写、调试、维护。后者效率较高。
3、独身版本的两个实现形式:
template<class T> const T operator+(const T& lhs,const T& rhs) { return T(lhs) += rhs; //产生临时对象} //version 2template<class T> const T operator+(const T& lhs,const T& rhs) { T result(lhs);//产生命名对象 return result+= rhs; }
第一个版本和第二版本几乎一样,但是却有个重要的差异,第二版本中含有一个命名对象result,而第一版本中拥有返回值优化,使得编译器具有最佳的效果。匿名对象总是比命名对象更容易消除,所以当你面临命名对象和临时对象的抉择时,最好是选择临时对象。它绝不会比其命名对象耗用更多成本,反倒是极有可能降低成本。
23、考虑使用其它程序库
略过。
24、了解 virtual functions、multiple inheritance、virtual base classes、runtime type identification 的成本
1、使用虚函数,会使用所谓的 virtual tables 和 virtual table pointers ,通常简写为 vtbls 和 vptrs 。vtbl通常是一个函数指针的数组或链表,每一个声明或继承虚函数的类都有自己的vtbl,其中的每一个元素就是该类的各个虚函数的指针。
虚函数所需的代价:
(1)必须为每个包含虚函数的类的virtual table留出空间;
(2)每个包含虚函数的类的对象里,必须为额外的指针付出代价;
(3)实际上放弃了使用内联函数,虚函数是运行时绑定的,而 inline 是编译时展开的,即使你对虚函数使用 inline ,编译器也通常会忽略。
2、多继承时,在单个对象里有多个vptr(一个基类对应一个),”找出对象内的vptrs”会变得比较复杂,它和虚基类一样,会增加对象体积的大小。
多重继承往往导致virtual base classes(虚拟基类)的需求。在non-virtual base的情况下,如果派生类对于基类有多条继承路径,那么派生类会有不止一个基类部分,让基类为virtual可以消除基类的数据成员在每一个子类复制滋生。然而虚基类也可能导致另一成本:其实现做法常常利用指针,指向”virtual base class”部分,因此对象内可能出现一个(或多个)这样的指针。例如多重继承的”菱形”结构。
3、RTTI能让我们在运行时找到对象和类的有关信息,所以肯定有某个地方存储了这些信息让我们查询,这些信息被存储在类型为type_info的对象里。通常,RTTI被设计为在类的vbtl上实现。
- 《More Effective C++》读书笔记-效率
- <<More Effective C++>>读书笔记4: 效率
- More Effective C++读书笔记---效率
- 《more effective c++》读书笔记
- 《More Effective C++》读书笔记一
- 《More Effective C++》读书笔记-异常
- 《More Effective C++》读书笔记-技术
- 《more effective c++》基础部分读书笔记
- 《More Effective C++》读书笔记-基础议题
- 《More Effective C++》读书笔记-操作符
- 《More Effective C++》读书笔记-技术(二)
- <<More Effective C++>>读书笔记1: 基础议题
- <<More Effective C++>>读书笔记2: 运算符
- <<More Effective C++>>读书笔记3: 异常
- <<More Effective C++>>读书笔记6: 杂项
- <<More Effective C++>>读书笔记5: 技巧(1)
- <<More Effective C++>>读书笔记5: 技巧(2)
- 【more effective c++读书笔记】【第4章】效率(1)
- 使用npm安装一些包失败了的看过来(npm国内镜像介绍)
- SortedSet和TreeSet
- 《hadoop进阶》web日志系统 KPI指标的分析与实现
- ztr loves math
- javascript 抽奖
- 《More Effective C++》读书笔记-效率
- 多种多样APP主界面Tab实现
- servlet、jsp跳转(传值)总结及URL传参数
- 第二次打字测试
- linux内存源码分析 - 内存回收(lru链表)
- Java重拾之猜数字小游戏
- bootstrap表单验证插件 经验记录 与RSA加密事件配合修改
- Android广播机制
- C经典 快速实现加减乘除