C++进阶
C++对象模型,C++模板类,Effective C++
kktiandao
stay hungry stay foolish
展开
-
Item24理解虚拟函数、多继承、虚基类和 RTTI 所需的代价
理解虚拟函数、多继承、虚基类和 RTTI 所需的代价类的虚拟函数时通过vtbl和vptr实现的;编译时确定vtbl的存放位置;一般采用启发式算法;在遇到第一个包含类的非内联虚函数的object文件中存放vtbl文件;而后进行链接;虚基类主要是解决类多继承的二义性问题;运行时类型推导(RTTI)主要时每个类型有一个typeinfo对象;通过typeid操作符可以访问typeinfo;typeinfo的实现是基于vptr的;每个对象的vptr的0位存放有指向typeinfo的指针。...原创 2020-11-19 15:55:53 · 119 阅读 · 0 评论 -
Item23考虑变更程序库
考虑变更程序库不同程序库的特性不同程序设计需考虑方方面面的因素:如速度、内存消耗、可扩展性、可维护性等,但诸多方面难以兼顾,故程序设计是折中的过程。选择程序库时,可根据当前程序设计的主要方向及优化瓶颈对类似功能的多种程序库加以评估;例子iostream和stdio都可以实现文件输出;对多数案例来讲,iostream比stdio要慢;且生成的程序要大一些。如果程序设计中有大量io操作,且要求性能较高,则需考虑stdio;如果程序设计中涉及到不同类型的文件读取,或后续用户会扩展自定义类型的文件读取原创 2020-11-19 15:46:21 · 106 阅读 · 0 评论 -
ITEM21:通过重载避免隐式类型转换
通过重载避免隐式类型转换如下,隐式类型转换会增加临时变量的产生;class UPInt { // unlimited precisionpublic: // integers 类UPInt();UPInt(int value);...};const UPInt operator+(const UPInt& lhs, const UPInt& rhs);UPInt upi1, upi2;...UPInt upi3 = upi1 + upi2;upi3 = upi1原创 2020-11-10 17:02:47 · 83 阅读 · 0 评论 -
ITEM19、20 理解临时对象的来源
理解临时对象的来源关于临时变量临时对象是匿名的非堆对象,而非局部对象;临时对象往往是为了是函数成功调用而进行的隐式类型转换和函数返回而建立的;问题:临时对象比较占用资源任何时候只要有常量引用参数,就存在建立临时对象而绑定在参数上的可能性;(隐式类型转换)任何时候只要见到函数返回对象(传值),就存在临时对象的被建立;解决方案可以使用右值引用来解决临时对象的问题;针对返回对象的问题,可以返回 constructor argument 而不是直接返回对象;此时c++编译器会优化掉函数原创 2020-11-10 17:02:05 · 113 阅读 · 0 评论 -
ITEM10在构造函数中防止资源泄漏
在构造函数中防止资源泄漏原则资源应该被封装在一个对象里,遵循这个规则,你通常就能避免在存在异常环境里发生资源泄漏。问题C++仅仅能删除被完全构造的对象(fully contructed objects), 只有一个对象的构造函数完全运行完毕,这个对象才被完全地构造。void testBookEntryClass(){BookEntry *pb = 0;try {pb = new BookEntry("Addison-Wesley Publishing Company","One Ja原创 2020-11-06 17:25:17 · 94 阅读 · 0 评论 -
ITEM9 使用析构函数防止资源泄露
使用析构函数防止资源泄露原则:资源应该被封装在一个对象里,遵循这个规则,你通常就能避免在存在异常环境里发生资源泄漏。少用局部资源的raw指针。问题当从堆上建立对象,并使用指针调用对象的函数。在删除对象前,如果发生异常,可能会造成对象无法正常释放。void processAdoptions(istream& dataSource){while (dataSource) { // 还有数据时,继续循环ALA *pa = readALA(dataSource); //得到下一个动物原创 2020-11-06 15:31:39 · 117 阅读 · 0 评论 -
ITEM8理解不同含义的NEW和DELETE
理解不同含义的NEW和DELETE原则:可以改变New的实现方式,但是改变不了New要实现什么。分类:a. new /new[] (new operator);b. operator new/operator new[]c. placement new区别new operatornew operator是语言内置的,不可改变;new operator的实现分两步:a. 调用operator new来分配内存(raw); b. 调用对象的构造函数,在a分配的内存上构建对象并返回对象指针。原创 2020-11-05 16:26:59 · 153 阅读 · 0 评论 -
ITEM7不要重载“&&”“||”或“,”
不要重载“&&”“||”或“,”原则重载操作符时要保证重载前后行为特性一致;不可重载的操作符. .* :: ?: new delete sizeof typeid static_cast dynamic_cast const_cast reinterpret_cast可以重载的操作符operator new operator deleteoperator new[] operator delete[]+ - * / % ^ & | ~! = < > +=原创 2020-11-05 10:42:21 · 139 阅读 · 0 评论 -
ITEM6自增和自减操作符前缀与后缀的区别
自增和自减操作符前缀与后缀的区别原则:使用自定义类的自增(减)操作时,前缀操作比后缀操作效率更高。后缀操作符是以前缀操作符的基础实现的。实现:在实现上,通过参数对前后缀操作符加以区分;后缀操作符有int型形参。前缀操作符返回引用,可连续调用,后缀返回const型的拷贝,不可以连续调用。因为后缀操作每次要建立临时变量并返回,所以效率比较低。特别是在循环中,应少用后缀造作符。class UPInt { // "unlimited precision int"public:UPInt&原创 2020-11-04 14:11:14 · 388 阅读 · 0 评论 -
ITEM5谨慎定义类型转换函数及单参数构造函数
谨慎定义类型转换函数及单参数构造函数类型转换的分类显示类型转换;隐式类型转换;隐式转换的实现方式定义单参数构造函数定义operator type()函数,如operator double();隐式类型转换的问题隐式类型转化是编译器的自发行为,使用方便但往往不可控,一旦出现业务问题极难调查;隐式转换造成代码晦涩不易维护;解决方案原则:尽量少用隐式转换;定义单参数构造函数时加explicit关键字;定义转换函数时,函数名不使用语法关键字,如operator asDoubl原创 2020-11-04 11:34:15 · 114 阅读 · 0 评论 -
ITEM4避免无用的缺省构造函数
避免无用的缺省构造函数有些对象不利用外部数据就进行初始化时不合理的;入公司或个人的ID;提供无用的缺省构造,增加其他成员函数对成员变量合法性的判断及错误处理;是的类的处理效率降低;没有缺省构造函数的不便没有缺省构造函数时,不方便在堆上直接建立数组;因为new不支持传参;模板没有缺省构造函数时,不利于与其他模板配合;设计虚基类时,没有缺省构造函数,其所有子类都需要为积累传参;...原创 2020-11-04 11:20:53 · 135 阅读 · 0 评论 -
ITEM3不要对数组使用多态
不要对数组使用多态多态和指针算法不能混用;数组和多态也不能混用;(尽量不要从具体类派生具体类)如果不从具体类派生出另一个具体类,就不太可能使用多态性数组的错误;array[I]的寻址是array + i * sizeof(class);当array类型为基类的数组;但实际存放对象为子类;指针算法中寻址会出现错误;delete[]也易出现错误;...原创 2020-11-04 11:18:20 · 105 阅读 · 0 评论 -
ITEM2尽量使用C++风格的类型转换
尽量使用C++风格的类型转换原则:类型转换要力求语义明确。C风格类型转换允许使用者在任意两个类型间进行转换,不对转换进行细分且语义不明确。C++风格的类型转换操作符:static_cast:基本与C风格类型转换类似;const_cast:去掉表达式的const或volatileness属性;dynamic_cast:安全的沿着类的继承方向向下进行类型转换;即可将基类指针或引用转换成派生类的指针或引用;当转换失败时返回空指针或抛出异常。dynamic_cast在推导继承关系时,不能用于缺乏虚函数原创 2020-11-04 11:11:47 · 80 阅读 · 0 评论 -
ITEM1引用与指针
引用与指针原则:C++中引用必须初始化;指针可以不初始化,默认为空;不存在指向空值的引用,这意味使用引用比使用指针效率高。因为在使用引用之前不用验证其合法性。指针可以被重新赋值,以指向另一个不同的对象。但引用则总是指向初始化时指定的对象,以后不可改变。当存在不指向任何对象的情况,以及存在指向对象变换的情况,应使用指针。反之则使用引用。重载操作符时,尽量返回引用。...原创 2020-11-04 11:02:56 · 371 阅读 · 0 评论 -
ITEM11 禁止异常传递到析构函数外部
异常信息传递至析构函数外部会导致:terminate函数可能被调用;导致程序异常终止; 异常传递出析构函数后,会导致异常发生处后面的语句无法执行。漏掉部分业务逻辑。在析构函数中可使用 try catch blockSession::~Session(){try {logDestruction(this);}catch (...) {//防止catch中再次抛出异常,此处选择...原创 2020-04-02 09:43:32 · 124 阅读 · 1 评论