Effective C++条款(第三版-侯杰译)

条款一:视C++为一个语言联邦

        【C++高效编程守则视情况而变化,取决于你使用的C++哪一部分】

条款二:尽量以const,enum,inline替换#define

        【对于单纯变量,最好以const对象或enums替换#defines]

        【对于形似函数的宏,最好改用inline函数代替#define】

条款三:尽可能使用const

        【将某些东西声明为const可帮助编译器侦测出错误用法, const可被施加于任何作用域内的对象、函数参数、函数返回类型、成员函数本体】

        【编译器强制实施bitwise constness(位常数),但你编写程序时应该使用“概念上的常量性”】

        【当const和non-const成员函数有着实质等价的实现时,令non-const版本调用const版本可避免代码重复】

条款四:确定对象被使用前已先被初始化

        【为内置型对象进行手工初始化,因为C++不保证初始化它们】

        【构造函数最好使用成员初值列,而不要在构造函数本体内使用赋值操作,初值列列出的成员变量,其排序次序应该和它们在class中的声明次序相同】

        【为避免“跨编译单元之初始化次序”问题,请以local static(局部静态变量)对象替换non-localstatic(全局静态变量)对象】

条款五:了解C++默默编写并调用哪些函数

        【编译器可以暗自为class创建默认构造函数、默认复制函数、默认=操作符以及析构函数】

条款六:若不想使用编译器自动生成的函数,就该明确拒绝

        【为驳回编译器自动提供的机能,可将相应的成员函数声明为private并且不予实现,或者使用不可复制的基类也是一种做法】

扫描二维码关注公众号,回复: 15527840 查看本文章

条款七:为多态积累生命virtual析构函数

        【带多态性质的基类应该声明一个virtual析构函数,如果class带有任何virt函数,他就应该有一个virtual析构函数】

        【Classes的设计目的如果不是作为基类使用,或不是为了具备多态性,就不该声明virtual析构函数】

条款八:别让异常逃离析构函数

        【析构函数绝对不要吐出异常,如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常然后吞下它们或者结束程序】

        【如果客户需要对某个操作函数运行期间抛出的异常作出反应,那么class应该提供一个普通函数执行该操作】

条款九:绝不在构造和析构过程中调用virtual函数

        【在构造和析构期间不要调用virtual函数,因为这类调用不会下降至派生类】

条款十:令operator=返回一个reference to *this

        【令赋值操作符返回一个reference to *this】

条款十一:在operator=中处理“自我赋值”

        【确保当对象自我赋值时 operator= 有良好行为。其中技术包括比钱“来源对象”和“目标对象”的地址、精心周到的语向顺序、以及copyand-swap•】
        【二确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确】

条款十二:复制对象时不要忘了每一个成分

        【复制函数应该保证复制”对象内的所有成员变量“及所有的基类成分】

        【不要尝试以某个赋值函数实现另一个复制函数,应该将共同机能放进第三个函数中,并由两个复制函数共同调用】

条款十三:以对象管理资源

        【为防止资源泄露,请使用RALL对象,他们在构造函数中获得资源并在析构函数中释放资源】

        【两个常被使用的RALL 类分别是trl::shared_ptr和auto_shared,前者通常是较佳选择,因为其复制行为比较直观,如果auto_ptr,复制动作会使它指向NULL】

条款十四:在资源管理类中小心复制行为

        【复制RALL对象必须一并复制它所管理的资源,所以资源的复制行为决定了RALL对象的复制行为】

        【普遍而常见的RALL 类复制行为是:抑制复制、施行引用计数法,不过其他行为也可以实现】

条款十五:在资源管理类中提供对原始资源的访问

        【API往往要求访问原始资源,所以每一个RALL类应该提供一个”取得其所管理之资源”的方法】

        【对原始资源的访问可能会经由显式转换或隐式转换,一般而言显式转换比较安全,但隐式转换对用户比较方便】

条款十六:成对使用new和delete时要采取相同形式

        【如果你在new中使用[],必须在相应的delete表达式中也使用[],如果你在new表达式中不使用[],那么一定不要在相应的delete表达式中使用[]】

条款十七:以独立语句将newed对象置入智能指针

        【以独立语句将newed对象存储于智能指针内,如果不这样做,一旦异常被抛出,有可能导致难以察觉的资源泄露】

条款十八:让接口容易被正确的使用,不易被误用

        【好的接口容易被正确使用,不容易被误用,你应该在你的所有接口中努力达成这些性质】

        【“促进正确使用”的办法包括接口的一致性以及与内置类型的行为兼容】

        【“阻止误用”的办法包括建立新类型、限制类型上的操作,束缚对象值,以及消除客户的资源管理责任】

        【trl:shared_ptr支持定制型删除器,这可防范DLL问题,可被用来自动解除互斥锁等待】

条款十九:设计class犹如设计type

        【class的设计就是type的设计,在定义一个新的type之前,请确定你已经考虑过本条款覆盖的讨论题】

条款二十:宁以pass-by reference-to-const替换pass-by-value

        【尽量以pass-byreference-to-const替换pass-byvalue。前者通常比较高效,并可避免切割问题 (slicing problem)。】
        【以上规则并不适用于内置类型,以及 STL 的迭代器和西数对象。对它们而言,pass-by-value往往比较适当]

条款 21:必须返回对象时,别妄想返回其 reference

        【绝不要返回 pointer 或 reference 指向一个 local stack 对象,或返回 reference 指向一个heap-allocated 对象,或返回 pointer 或reference 指向一个 local static 对象而有可能同时需要多个这样的对象。条款 4 已经为“在单线程环境中合理返回 reference
指向一个 local static 对象”提供了一份设计实例。】

条款二十二:将成员变量声明为private

        【切记将成员变量声明为private。这可赋予客户访问数据的一致性,可惜为划分访问控制,允诺约束条件获得保证。并提供class作者以充分的弹性】

        【protected并不比public更具封装性】

条款二十三:宁以non-member、non-friend替换member函数

        【宁可拿non-member、non-friend替换member函数,这样可以增加封装性,包裹弹性,和机能扩充性】

条款二十四:若所有参数皆需类型转换,请为此采用non-member函数

        【如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member】

条款二十五:考虑写出一个不抛出异常的swap函数

        【当std::swap 对你的类型效率不高时,提供一个swap 成员函数,并确定这个函数
不抛出异常】
        【如果你提供一个member swap,也该提供一个 non-member swap 用来调用前者。对手classes(而非 templates),也请特化 std::swap】
        【调用swap时应针对std!:swap使用using 声明式,然后调用swap 并且不带任何“命名空间资格修饰”】
        【为“用户定义类型”进行 stdtempltes 全特化是好的,但千万不要尝试在std内加入某些对 std而言全新的东西】

条款二十六:尽可能延后变量定义式的出现时间

        【尽可能延后变量定义式的出现,这样可以增加程序的清晰度并改善程序效率】

条款二十七:尽量少做转型动作

        【如果可以,尽量避免转型,特别是在注重效率的代码中避免 dynamic_ castso
如果有个设计需要转型动作,试着发展无需转型的替代设计】
        【如果转型是必要的,试着将它隐藏于某个函数背后。客户随后可以调用该函数,而不需将转型放进他们自己的代码内】
        【宁可使用 C+t-style(新式)转型,不要使用1旧式转型。前者很容易辦识出来,而且也比较有着分门别类的职掌】

条款二十八:避免返回handles指向对象内部成分

       【避免返回handles指向对象内部,遵守这个条款可增加封装性,帮助cosnt成员函数的行为像个const,并将发生”虚吊号码牌“的可能性降至最低】

条款二十九:为“异常安全“而努力是值得的

      【异常安全函数 (Exception-safe functions)即使发生异常也不会泄漏资源或允许任何数据结构败坏。这样的函数区分为三种可能的保证:基本型、强烈型、拋异常型】
        【“强烈保证”往往能够以 copy-and-swap 实现出来,但“强烈保证” 并非对所有函数都可实现或具备现实意义】
        【函数提供的 “异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证” 中的最弱者】

条款三十:彻底了解inlining的里里外外

        【将大多数inlining限制在小型、被频繁调用的函数身上,这可使日后的调试过程和二进制升级更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化

        【不要只因为function template出现在头文件,就将它们声明为inline】

条款三十一:将文件的编译依存关系降至最低

        【支持“编译依存性最小化”的一般构想是:相依于声明式,不要相依于定义式。基于此构想的两个手段是handle class 和interface class】

        【程序库头文件应该以“完全且仅有声明式”的形式存在,这种做法不论是否设计template都适用】

条款三十二:确定你的public继承塑膜出is-a关系

        【public继承意味is-a,都适用基类上的每一件事情一定也适用于派生类,因为每一个派生类对象也是一个基类对象】

条款三十三:避免遮掩继承而来的名称

        【派生类的名称会遮掩基类内的名称,在public继承下从来没有人希望如此】

        【为了让被遮掩的名称再见天日,可使用using声明式或转交函数】

条款三十四:区分接口继承和实现继承

        【接口继承和实现继承不同,在public继承之下,派生类总是继承基类的接口】

        【纯虚函数只具体指定接口继承】

        【简单的虚函数具体指定接口继承及缺省实现继承】

        【非虚函数具体指定接口继承以及强制性实现继承】

条款三十五:考虑virtual函数以外的其他选择

        【virtual函数的替代方案包括 NVI 手法及 Strategy 设计模式的多种形式。NVI手
法自身是一个特殊形式的 Template Method 设计模式】
        【将机能从成员两数移到class 外部函数,带来的一个缺点是,非成员函数无法访问class 的non-public 成员】
        【tr1:function对象的行为就像一般函数指针。这样的对象可接纳“与给定之目标签名式 (target signature) 兼容” 的所有可调用物 (callable entities)】

条款三十六:绝不重新定义继承而来的非虚函数

        【绝对不要重新定义而来的非虚函数】

条款三十七:绝不重新定义继承而来的缺省参数值

        【绝对不要重新定义一个继承而来的缺省参数值。因为缺省参数值都是静态绑定,而virtual函数-你唯一应该复写的东西-确实动态绑定的】

条款三十八:通过复合塑膜出has-a或”根据某物实现出

        【复合的意义和public继承完全不同】

        【在应用域,复合意味has-a,在实现域,复合意味is-implemented-terms-of】

条款三十九:明智而审慎地使用private继承

        【Private 继承意味 is-implemented-in-ters of(根据某物实现出)。它通常比复合的级别低。但是当 derived class 需要访问 protected base class 的成员,或需要重新定义樂承而的 virtual 两数时,这么设计是合理的】
        【和复合 (composition)不同,private 继承可以造成empty base 最优化。这对致力于“对象尺寸最小化” 的程序库开发者而言,可能很重要】

条款四十:明智而审慎的使用多重继承

        【多重樂承比单一继承复杂。它可能导致新的歧义性,以及对virtual 继承的需要。

        【virtual 继承会增加大小、速度、初始化(及赋值)复杂度等等成本,如果virtual base class 不带任何数据,将是最具实用价值的情况】
        【多重继承的确有正当用途。其中一个情节涉及“public 继承某个 Interface class”和“private 继承某个协助实现的 class”〞 的两相组合】

条款四十一:了解隐式接口和编译期多态

        【classes 和 templates 都支持接口(iterfaces )和多态 (polymorphism)】
        【对classes 而言接口是品式的(explicit),以函数签名为中心。多态则是通过 virtual
函数发生于运行期】
        【对template 参数而言,接口是隐式的 (implicit),奠基于有效表达式。多态则是通过 template 具现化和函数重载解析 (function overloading resolution)发生于编译期】

条款四十二:了解typename的双重含义

        【声明template参数时,前缀关键字class和typename可以互换】

        【请使用关键字typename标识嵌套从属类型名称,但不得在基类列或成员初值列内以它作为基类修饰符】

条款四十三:学习处理模板化基类内的名称

        【可在派生模板内通过"this->"指涉基类模板内的成员名称,或由一个明白写出的“基类资格修饰符”完成】

条款四十四:将与参数无关的代码抽离templates

        【Templates 生成多个classes 和多个函数,所以任何 teraplate 代码都不该与某个造
成膨胩的 template 参数产生相依关系】
        【因非类型模板参数 (non-type template parameters)而造成的代码膨账,往往可消除,做法是以函数参数或class 成员变量替换template 参数】
        【因类型参数 (type parameters)而造成的代码膨胩,往往可降低,做法是让带有完全相同二进制表述 (binary representations)的具现类型 (instantiation types)共享实现码】

条款四十五:运用成员函数模板接受所有兼容类型

        【请使用成员函数模板生成“可接受所有兼容类型”的函数】

        【如果你声明成员模板用于”泛化复制构造或=操作符“,你还是需要生命正常的复制构造函数和=操作符】

条款四十六:需要类型转换时请为模板定义非成员函数

        【当我们编写一个类模板,而它所提供的与此模板相关的函数支持所有参数之隐式类型转换时,请将那些函数定义为类模板内部的友元函数】

条款四十七:请使用traits classes表现类型信息

        【traits classes使得”类型相关信息“在编译期可用,它们以templates和”templates特化“完成实现】

        【整合重载技术后,traits classes有可能在编译期对类型执行if-else测试】

条款四十八:认识template元编程

        【Template metaprogramming (TMP,模板元编程,可将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率】
        【TMP 可被用来生成“基于政策选择组合〞 (based oa combinations ot policychoices)的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码】

条款四十九:了解new-handler的行为

        【set_new_handler允许客户指定一个函数,在内存分配无法获得满足时被调用】

        【Nothrow new是一个颇为局限的工具,因为它只适用于内存分配,后记得构造函数调用还是可能抛出异常】

条款五十:了解new和delete的合理替换时机

        【有许多理由需要写个自定的new和delete,包括改善效能、对heap运用错误进行调试、手机heap调用信息】

条款五十一:编写new和delete时需固守常规

        【operator new 应该内含一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就该调用 new-handler。它也应该有能力处理0 bytes 申请。Class专属版本则还应该处理“比正确大小更大的(错误)〉申请”】
        【operator delete 应该在收到null 指针时 不做任何事。Class 专属版本则还应该处理 “比正确大小更大的(错误)申请”】

条款五十二:写了placement new也要写placement delete

        【当你写一个 placement operator new, 请确定也写出了对的placement operator delete。如果没有这样做,你的程序可能会发生隐微而时断时续的内存泄漏】
        【当你声明placerrent mew 和 placerment delete,请确定不要无意识(非故意)地遮掩了它们的正常版本】

条款五十三:不要轻忽编译器的警告

        【严肃对待编译器发出的警告信息,努力在你的编译器的最高警告级别下争取”无任何警告“的荣誉】

        【不要过度以来编译器的报警能力,因为不同的编译器对待事情的态度并不相同,一旦移植到另一个编译器上,你原本依赖的警告信息有可能丢失】

条款五十四:让自己熟悉包括TR1在内的标准程序库

        【C++标准程序库的主要机能由 STL、iostreams、 1ocales 组成。并包含C99 标准
程序库】
        【TRI 添加了智能指针(例如 tr1::shared ptr)、一般化函数指针(tr1::function)、hash-based 容器、正则表达式 (regular expressions)以及另外 10个组件的支持】
        【TRI 自身只是一份规范。为获得 TR1 提供的好处,你需要一份实物。一个好的
实物来源是 Boost】

条款五十五:让自己熟悉Boost

        【Boost是一个社群,也是一个网站,致力于免费、源码开发、同僚复审的C++程序库开发,Boost在C++标准化过程中扮演深具影响力的角色】

        【Boost提供许多TR1组件实现品,以及其他许多程序库】

        

      

猜你喜欢

转载自blog.csdn.net/pan_1214_/article/details/127735641