《More Effective C++》笔记

来源:互联网 发布:电路图模拟软件 编辑:程序博客网 时间:2024/04/30 12:58

Item M2: 尽量使用C++风格的类型转换。为什么?static_cast,const_cast,dynamic_cast,reinterpret_cast这四种类型转换具有明确的语义,有利于表达程序员的意图。同时每个类型转换也都也一些限制,有利于编译器检查。static_cast是最普通的类型转换,const_cast 用于去掉类型的const属性,dynamic_cast沿着继承关系向下转换类型,也就是从基类的指针或引用转换成派生类的指针或引用,如果不能转换会报出异常;reinterpret_cast是功能最强大的类型转换,是直接从内存层面进行转换的,Patricia树中就用到了很多这种技巧;

Item M3:不要使用数组多态;例子参见原文。原因是编译器遍历数组是依赖于数组中元素的大小的,必须要明确告诉编译器。另外,派生类对象的大小和基类对象的大小肯定是不一样的。如果一个函数的形参申明为基类对象的数组,绑定的实参是派生类对象的数组,那么编译器在遍历这个数组时就会出错。

Item M5:将单参数的构造函数申明成explicit,避免隐式类型转换。

当我们自定义一个类类型时,单参数的构造函数能够作为隐式类型转换函数。所谓单参数的构造函数是指只有一个参数的构造函数,也包括除第一个参数外其余参数均有默认实参的多参数构造函数。隐式类型转换函数什么时候调用?当我们因为笔误写出一个错误的表达式,这个表达式因为类型不匹配应该不能通过编译。但是编译器会尝试各种隐式类型转换函数使得上述错误的表达式通过编译。这实际上就会造成不宜察觉的bug。为避免这种情况,将单参数的构造函数申明成explicit。

定义隐式类型转换造成的弊端大于便利,因此不要定义隐式类型转换。

有两种方法可以定义隐式类型转换:一是单参数构造函数,二是隐式类型转换函数,其声明形如operator double() const;


Item M9:对操作局部资源的指针说再见。正常流程是局部资源new出来、处理业务、delete局部资源。如果在处理业务过程出现异常,则delete局部资源的代码无法调用,内存泄漏了。对策是用类指针的对象(例如auto_ptr)包含new出来的对象,则类指针对象的析构函数中会delete在构造函数中new出来的内存。即使出现异常,类指针对象的析构函数也会正常调用。该对策背后的思想是:用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源。

规则:资源应该被封装在一个对象里。


Item M10: C++仅仅能删除被完全构造的对象(fully contructed objects), 只有一个对象的构造函数完全运行完毕,这个对象才被完全地构造。C++拒绝为没有完成构造操作的对象调用析构函数。

正常流程是构造函数new资源、析构函数释放资源。如果构造函数new两个资源,在new第二个资源时出现异常,则该对象是未完全构造的对象,析构函数不会被调用,new出来的第一个资源泄漏了。

对策:将资源包含在类指针的对象(例如auto_ptr)中。

该Item讨论的问题是:构造函数中出现异常则会导致资源泄漏。

0 0
原创粉丝点击