Effective C++精炼
抓取Effective C++要点,节约阅读成本,提高复习效率。
qq_42316947
这个作者很懒,什么都没留下…
展开
-
54 让自己熟悉包括TR1在内的标准程序库
54 让自己熟悉包括TR1在内的标准程序库原创 2020-07-22 19:37:35 · 211 阅读 · 0 评论 -
52写了 placement new 也要写 placement delete
52写了 placement new 也要写 placement delete对于placement new,我们需要同时提供正常的 operator delete(用于构造期间无任何异常抛出)和一个placement 版本:placement delete 只在“伴随placement new 触发的构造函数”出现异常时才会被调用。声明placement new 和 placement delete时,确定无意遮掩它们的正常版本,方法如下:建立一个基类,内含所有正常形式的new 和 del原创 2020-07-22 17:29:50 · 207 阅读 · 0 评论 -
51 编写 new 和delete 时需固守常规
51 编写 new 和delete 时需固守常规必须遵守的规则须得返回正确的值;内存不足时须得调用new-handling 函数;须有对付零内存需求的准备;避免掩盖正常形式的 new 或者 delete。非成员 operator new 伪码:operator new 成员函数可能被继承时:成员 operator delete 伪码:...原创 2020-07-22 16:44:55 · 258 阅读 · 1 评论 -
49了解 new-handler 的行为
49了解 new-handler 的行为new-hander 是个typedef, 定义出一个指向函数的指针。new-hander 函数需要做的事:如何让不同的类使用不同的new-hander:“怪异的循环模板模式”(CRTP)原创 2020-07-22 16:08:50 · 200 阅读 · 0 评论 -
48 认识template 元编程
48 认识template 元编程TMP两大优点缺点编译器必须确保所有源码都有效,纵使是不会执行的代码原创 2020-07-22 10:31:36 · 145 阅读 · 0 评论 -
47 请使用traits class 表现类型信息
47 请使用traits class 表现类型信息知识点补充STL五大迭代器:input 迭代器,output 迭代器,forward迭代器,bidirectional 迭代器,random access 迭代器原创 2020-07-22 09:33:26 · 140 阅读 · 0 评论 -
46 需要类型转换时请为template 定义非成员函数
46 需要类型转换时请为template 定义非成员函数template 实参推导过程中不考虑隐式转换错误示范:定义成非成员非友函数,混合调用时编译期将出现错误;2.在1的基础上在模板类内将其声明为友函数,连接期出现错误;正确版本将定义式放在模板类中:改进版本上一版本的operator* 为内联函数,解决办法: 在模板类外定义一个辅助模板函数,operator* 对其进行调用,以此避免内联函数带来的弊端...原创 2020-07-21 22:36:33 · 96 阅读 · 0 评论 -
45 运用成员函数模板接受所有兼容类型
45 运用成员函数模板接受所有兼容类型例子:注:如果你声明member templates用于“泛化copy构造”或“泛化assignment操作”,你还是需要声明正常的 copy 构造函数和 copy assignment 操作符。原创 2020-07-21 21:50:52 · 177 阅读 · 0 评论 -
44 将与参数无关的代码抽离 template
44 将与参数无关的代码抽离 template以下例子会具现化两份,造成代码膨胀:解决办法如何调用数据:注:这个条款只讨论由non-type template parameters(非类型模板参数)带来的膨胀,这个条款只讨论由non-type template parameters(非类型模板参数)带来的膨胀。...原创 2020-07-21 20:54:16 · 130 阅读 · 0 评论 -
43 学习处理模板化的基类内名称
43 学习处理模板化的基类内名称编译器往往拒绝在模板化基类内寻找继承而来的名称:上述代码无法编译通过的原因MsgSender 可能被特化,编译器无法确定 Company 有 sendClear 函数,比如 MsgSender 被特化为:3种解决方法在基类函数调用之前加上 “this->” : 使用using 声明式:调用时明确写出资格修饰符:...原创 2020-07-21 19:44:17 · 187 阅读 · 0 评论 -
42 了解typename 的双重意义
42 了解 typename 的双重意义声明template 参数时,class 与 typename 并无区别当在template 中指涉一个嵌套从属类型名称时,需要在紧邻它的前面加上关键字 typename。例外:typename 不应该出现在基类列表(base class list)的嵌套从属类型名称前,也不可在成员初值列表(member initialization list)中作为基类(base class)的修饰符。typename 可能会影响可移植性,因为有的编译器不接受...原创 2020-07-21 17:11:56 · 129 阅读 · 0 评论 -
39 明智而审慎的使用private 继承
39 明智而审慎的使用private 继承对于private 继承,编译器不会自动将一个derived class 对象转换为base class 对象;private 继承意味着 implemented-in-terms-of使用复合加继承替换private的原因以免虚函数在以后的派生类中被继承降低文件间的编译依存性使用private 的原因及场景EBO(empty base optimization:空白基类最优化)...原创 2020-07-21 15:04:38 · 118 阅读 · 0 评论 -
38 通过复合塑膜出has-a 或“根据某物实现出”
38 通过复合塑膜出has-a 或“根据某物实现出”当复合发生在应用域的对象之间时,表现出has-a 关系;当复合发生在实现域,便表现出 is-implemented-in-terms-of 的关系名词解释应用域与实现域:原创 2020-07-21 14:02:39 · 152 阅读 · 0 评论 -
37 绝不重新定义继承而来的缺省参数值
37 绝不重新定义继承而来的缺省参数值virtual 函数系动态绑定(又名后期绑定),缺省参数值却为静态绑定(又名前期绑定)静态类型:所声明的类型;动态类型:所指对象的类型,可在程序执行过程中改变,通常由赋值完成调用virtual 函数时,究竟调用哪一份函数实现代码,取决于调用时那个对象的动态类型;注若想为派生类提供与基类相同的参数值,可使用使用NVI手法,让非虚函数提供缺省参数,如此可避免代码重复和相依性。...原创 2020-07-21 10:30:40 · 109 阅读 · 0 评论 -
35 考虑virtual 函数以外的其他选择
35 考虑virtual 函数以外的其他选择方法NVI(non-virtual interface)手法。原创 2020-07-21 09:40:33 · 157 阅读 · 0 评论 -
34区分接口继承和实现继承
34区分接口继承和实现继承声明 pure virtual 函数的目的是为了让derived class 只继承函数接口,具体实现须在derived class 中完成;声明impure virtual 函数的目的是为了让 derived class 继承该函数的接口和缺省实现,通过调用可在此缺省实现基础上添加新的代码;声明non-virtual 函数是为了让derived class 继承该函数的接口和强制性实现,绝不该在derived class 中重新定义,即不变性凌驾于特异性。注对pur原创 2020-07-20 22:08:38 · 83 阅读 · 0 评论 -
33 避免遮掩继承而来的名称
33 避免遮掩继承而来的名称derived class 作用域嵌套在 base class 作用域内:2.继承base class 某一函数的所有重载版本:使用using 声明。3.继承base class 某一函数的指定重载版本:使用转交函数(forwarding functions)...原创 2020-07-20 21:09:12 · 106 阅读 · 0 评论 -
32 确定你的public 继承塑膜出is-a 关系
32 确定你的public 继承塑膜出is-a 关系■ “public继承”意味is-a。适用于 base classes 身上的每一件事情一定也适用于 derived classes身上,因为每一个derived class对象也都是一个 class 对象。错误示例:企鹅和鸟的关系正方形和矩形...原创 2020-07-20 20:39:30 · 120 阅读 · 0 评论 -
31将文件间的编译依存性降至最低
31将文件间的编译依存性降至最低例子1.接口与实现分离的关键是以“声明依存性”替换“定义依存性”,如pimpl(pointer to implementation)。即Handle classse:Person的实现借用PersonImpl实现:2.原创 2020-07-20 20:18:59 · 138 阅读 · 0 评论 -
29 为异常安全努力是值得的
29 为异常安全努力是值得的“异常安全”的两个条件:1.不允许泄露任何资源;2.不允许数据败坏。反例:解决问题1:使用资源管理类,RAII对象解决问题2:1)使用资源管理类,如智能指针2)copy and swap异常安全保证基本保证、强烈保证、不抛掷(nothrow)保证...原创 2020-07-20 14:55:02 · 106 阅读 · 0 评论 -
28 避免返回handles 指向对象内部成分
28 避免返回handles 指向对象内部成分原因降低对象封装性以防空悬号码牌名词解释handles:号码牌,用来取得某个对象。原创 2020-07-20 11:20:26 · 84 阅读 · 0 评论 -
27 尽量少做转型动作
27 尽量少做转型动作四种新式转型const_cast(expression),将对象常量性移除;static_cast(expression),进行强迫隐式类型转换;如non_const到const,int到double;dynamic_cast(expression), 主要进行安全向下转换,速度较慢,用来决定对象是否属于继承体系中某个类型;reinterpret_cast(expression), 执行低级转型,不可移植。如pointer to int 到 int。dynamic_ca原创 2020-07-20 10:47:47 · 81 阅读 · 0 评论 -
26尽可能延后变量定义式的出现时间
26尽可能延后变量定义式的出现时间直到使用该变量前一刻,甚至到给它赋初值为止;对于循环:原创 2020-07-20 08:46:47 · 136 阅读 · 0 评论 -
25 考虑写出一个不抛异常的swap函数
25 考虑写出一个不抛异常的swap函数当自定义swap函数时,要确保该函数不会抛出异常。常出现在”pimpl 手法“(pointer to implementation)中。如果提供member swap,也应该提供non-member swap,对于classes (非templates),需要特化std::swap。...原创 2020-07-19 17:27:59 · 166 阅读 · 0 评论 -
24 若所有参数皆需类型转换,请为此采用non-member函数
24 若所有参数皆需类型转换,请为此采用non-member函数如果你需要为某个函数的所有参数(包括被this指针所指的那个隐喻参数)进行类型转换,那么这个函数必须是个non-member.至于是否使用friend 函数,要视情况而定。...原创 2020-07-19 16:10:43 · 151 阅读 · 0 评论 -
23 宁以non-member、non-friend 替换member函数
23 宁以non-member、non-friend 替换member函数原因member函数可以访问private 成员变量,降低了private 成员的封装性;而non-member、non-friend 函数不会。降低编译依存关系,增加包裹弹性,如下图:增加可扩充性。举个例子,如果某个 WebBrowser 客户决定写些与影像下载相关的便利函数,他只需要在WebBrowserStuff命名空间内建立一个头文件,内含那些函数的声明即可。新函数就像其他旧有的便利函数那样可用且整合为一体。.原创 2020-07-19 15:26:41 · 154 阅读 · 0 评论 -
22 将成员变量声明为private
22 将成员变量声明为private原因1.可细微划分访问控制、给予class作者充分的实现弹性。2. public成员变量没有封装性,当改变它时(比如移除),将会有许多客户代码被破坏;3. 与1相似,对于protected成员变量,改变它将会影响derived class。注不封装意味着不可改变。protected 不比 public更具封装性。...原创 2020-07-19 14:59:32 · 123 阅读 · 0 评论 -
21 必须返回对象时,别妄想返回其reference
21 必须返回对象时,别妄想返回其reference原因当指向local stack 对象时,函数结束后会自动销毁;当指向 heap-allocated 对象时,无法delete,造成资源泄露;示例:3. 当指向static 对象时,可能需要多个对象。示例:...原创 2020-07-19 14:21:40 · 77 阅读 · 0 评论 -
20 宁以 pass-by-reference-to-const 替换 pass-by-value
20 宁以 pass-by-reference-to-const 替换 pass-by-value优点效率高,无需多次调用构造函数和析构函数;防止对象被切割,derived class 被视为 base class。注内置类型、迭代器、函数对象可优选pass-by-value。...原创 2020-07-19 13:43:08 · 113 阅读 · 0 评论 -
18 让接口容易被正确使用,不易被误用
18 让接口容易被正确使用,不易被误用方法:使用类型系统(type system),如外覆类型(wrapper types)。示例:2. 尽量让自定义类型行为与内置类型行为一致。3. 如果要求客户必须记得做某些事情,就是有着“不正确使用”的倾向。示例:...原创 2020-07-19 12:50:52 · 137 阅读 · 0 评论 -
17 以独立语句将newed 对象置于智能指针
17 以独立语句将newed 对象置于智能指针原因: 在“资源被创建”和“资源转换为资源管理对象”之间可能产生异常,造成资源泄露。错误示范:正确示范:拆分原创 2020-07-19 10:33:15 · 82 阅读 · 0 评论 -
15 在资源管理类中提供对原始资源的访问
15 在资源管理类中提供对原始资源的访问APIs一般需要访问其原始资源,所以RAII class 要提供对原始资源访问的方法;方法:显示转换或者隐式转换(声明定义相关函数)。显示转换一般比较安全,一直转换对客户比较方便。...原创 2020-07-19 09:55:48 · 130 阅读 · 0 评论 -
14 在资源管理类中小心coping行为
14 在资源管理类中小心coping行为复制 RAII 对象时要记得复制它所管理的资源;常见的 RAII class coping行为:禁止 coping、使用引用计数法,如 tr1::shared_ptr。原创 2020-07-19 09:11:30 · 280 阅读 · 0 评论 -
13 以对象管理资源
13 以对象管理资源使用auto_ptr, 其析构函数自动调用delete,但当以copy 构造函数或者copy assignment 操作符复制它们时,它们会变成null。原创 2020-07-18 23:26:01 · 91 阅读 · 0 评论 -
12 复制对象时勿忘其每一个成分
12 复制对象时勿忘其每一个成分复制“对象内每个成员变量”以及“所有base class 成分”;不要以某个copying 函数调用另一个 copying 函数,应将两者的共同部分放在一个函数中,需要时再进行调用,该函数往往为 private。...原创 2020-07-18 21:06:12 · 121 阅读 · 0 评论 -
11 operator= 中处理“自我赋值”
11 operator= 中处理“自我赋值”3种方法:比较“目标对象”和“来源对象”的地址,但只有“自我赋值安全”,无“异常安全性”;调整语句顺序:先赋值后删除;使用copy构造函数和swap函数。...原创 2020-07-18 20:47:22 · 118 阅读 · 0 评论 -
9 绝不再构造和析构过程中调用virtual函数
9 绝不再构造和析构过程中调用virtual函数derived-class的构造函数被调用时,base class的构造函数一定更早被调用,此时对象的类型属于base class。解决方法:将virtual函数改为non-virtual,在 derived class 中使用 private static 方法产生 base class 构造时所需的信息,并将此信息上传至base class。相比于直接在derived class 初始化列表中给予base class 所需信息,这种方式更方便。原创 2020-07-18 20:10:53 · 94 阅读 · 0 评论 -
8 别让异常逃离析构函数
8 别让异常逃离析构函数如果析构函数可能抛出异常,则其应该能够捕捉任何异常,吞掉(不传播)或者终止程序(std::abort())。如果客户需要在函数运行期间抛出的异常做出反应,则class需要一个普通函数(而非在析构函数中)来执行析构函数中可能抛出异常的操作。...原创 2020-07-18 18:47:18 · 82 阅读 · 0 评论 -
7 为多态基类声明virtual虚构函数
7 为多态基类声明virtual虚构函数优点:1. 对于基类指针,当其指向衍生类时,可以完全销毁所指向的对象。声明virtual虚函数的缺点:1. 增加对象大小;2. 对象不再和其他语言(如C)内的相同声明有着一样的结构,因此就不能把它传递给其他语言所写的函数,该对象也就不再具有移植性。注:1.带多态性质的基类应该声明virtual析构函数。任何带有virtual函数的class必定有一个virtual虚构函数。因为带有virtual函数,说明该class要被继承。2. 不能继承带有“non-vi原创 2020-07-18 16:18:30 · 126 阅读 · 0 评论 -
6 若不想使用编译器自动生成的函数,就该明确拒绝
6 若不想使用编译器自动生成的函数,就该明确拒绝将成员函数声明为private而且故意不实现它们。根据 1 设计个base class,对其进行继承即可。优点:可以在编译期发现错误,而不是在连接期,尽管是在member函数或friend函数之内进行拷贝等操作。...原创 2020-07-18 15:22:42 · 101 阅读 · 0 评论