
Effective C++ 笔记
带你从头到尾复习一遍经典大作-Effective C++
HarlanC
程序员一枚
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
读书笔记 effective c++ Item 1 将c++视为一个语言联邦
Item 1 将c++视为一个语言联邦如今的c++已经是一个多重泛型变成语言。支持过程化,面向对象,函数式,泛型和元编程的组合。这种强大使得c++无可匹敌,却也带来了一些问题。所有“合适的”规则看上去都有例外。我们怎样理解这样一门语言?最容易的方法是不要将其看成单一的一门语言而是将其看成是一个有相关性的语言的联邦。在一个特定的子语言中,一些规则就比较简单,明确并且容易记忆。当你从一个子语言...原创 2017-02-06 22:24:00 · 127 阅读 · 2 评论 -
读书笔记 effective c++ Item 2 尽量使用const,枚举(enums),内联(inlines),不要使用宏定义(define)...
这个条目叫做,尽量使用编译器而不要使用预处理器更好。#define并没有当作语言本身的一部分。例如下面的例子:1 #define ASPECT_RATIO 1.653符号名称永远不会被编译器看到。它可能在源码到达编译器之前被预处理器移除。ASPECT_RATIO 最终不会进入符号表,如果因为这个常量的使用而导致编译错误,会使你非常迷惑,因为错误信息会指向1.653而不是ASPECT_...原创 2017-02-08 07:53:00 · 160 阅读 · 0 评论 -
读书笔记 effective c++ Item 3 在任何可能的时候使用 const
Const可以修饰什么? Const 关键字是万能的,在类外部,你可以用它修饰全局的或者命名空间范围内的常量,也可以用它来修饰文件,函数和块作用域的静态常量。在类内部,你可以使用它来声明静态或者非静态的数据成员。对于指针来说,你可以指定指针本身是不是const,指针指向的数据是不是const,两者可以同时为const或者两者同时为非const. 1 Char greeting[...原创 2017-02-09 23:01:00 · 145 阅读 · 0 评论 -
读书笔记 effective c++ Item 4 确保对象被使用前进行初始化
C++在对象的初始化上是变化无常的,例如看下面的例子:int x; 在一些上下文中,x保证会被初始化成0,在其他一些情况下却不能够保证。看下面的例子:class Point{int x,y;};Point p;P的数据成员有时候保证能够被初始化(成0),有时候却不能。如果你从不存在未初始化对象的语言中转到c++, 就需要注意了,因为这很重要。1. 使...原创 2017-02-11 20:23:00 · 158 阅读 · 0 评论 -
读书笔记 effective c++ Item 5 了解c++默认生成并调用的函数
1 编译器会默认生成哪些函数 什么时候空类不再是一个空类?答案是用c++处理的空类。如果你自己不声明,编译器会为你声明它们自己版本的拷贝构造函数,拷贝赋值运算符和析构函数,如果你一个构造函数都没有声明,编译器同样会为你声明一个默认拷贝构造函数。这些所有的函数会是public和inline的(Item30)。因此,如果你写了下面的类:1 class Empty{};本质上来说和下面的类...原创 2017-02-12 12:25:00 · 139 阅读 · 0 评论 -
读书笔记 effective c++ Item 6 如果你不想使用编译器自动生成的函数,你需要明确拒绝...
问题描述-阻止对象的拷贝 现实生活中的房产中介卖房子,一个服务于这个中介的软件系统很自然的会有一个表示要被销售的房屋的类:1 class HomeForSale { ... }; 每个房产中介会立刻指出来,要销售房屋的每个属性都是唯一的,没有两个完全一样的房屋。在这种情况下,拷贝一个HomeForSale对象就没有任何意义了。你在怎么能拷贝一些独一无二的东西呢?因此你可能会尝...原创 2017-02-13 09:03:00 · 125 阅读 · 0 评论 -
读书笔记 effective c++ Item 7 在多态基类中将析构函数声明为虚析构函数
1. 继承体系中关于对象释放遇到的问题描述1.1 手动释放关于时间记录有很多种方法,因此为不同的计时方法创建一个TimeKeeper基类和一些派生类就再合理不过了: 1 class TimeKeeper { 2 3 public: 4 5 TimeKeeper(); 6 7 ~TimeKeeper(); 8 9 ...10 11 };12 13 cla...原创 2017-02-13 19:01:00 · 152 阅读 · 0 评论 -
读书笔记 effective c++ Item 8 不要让异常(exceptions)离开析构函数
1.为什么c++不喜欢析构函数抛出异常C++并没有禁止析构函数出现异常,但是它肯定不鼓励这么做。这是有原因的,考虑下面的代码: 1 class Widget { 2 3 public: 4 5 ... 6 7 ~Widget() { ... } // assume this might emit an exception 8 9 };10 11 void do...原创 2017-02-14 07:34:00 · 195 阅读 · 0 评论 -
读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
1.关于构造函数的一个违反直觉的行为我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样。如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为这是c++同它们不一样的地方。假设你已经有一个为股票交易建模的类继承体系,它可以买卖股票等。这些交易的可审计性很重要,所以每次交易对象被创建的时候,需要在审计日志中创建一个合适的记录。这看上...原创 2017-02-15 00:04:00 · 142 阅读 · 0 评论 -
读书笔记 effective c++ Item 10 让赋值运算符返回指向*this的引用
一个关于赋值的有趣的事情是你可以将它们链在一起:1 int x, y, z;2 3 x = y = z = 15; // chain of assignments同样有趣的是赋值采用右结合律,所以上面的赋值链被解析成下面这个样子:1 x = (y = (z = 15));在这里,15被赋值给z,然后赋值的结果(更新的z)被赋值给y,再然后赋值的结果(更新的Y)被赋值给x。...原创 2017-02-15 23:42:00 · 125 阅读 · 0 评论 -
读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的当一个对象委派给自己的时候,自我赋值就会发生:1 class Widget { ... };2 3 Widget w;4 5 ...6 7 w = w; // assignment to self、这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的。此外,自身赋值也并不总是很容易的能够被辨别出来。举个例子:1 a[i] = a[...原创 2017-02-15 23:48:00 · 181 阅读 · 0 评论 -
读书笔记 effective c++ Item 12 拷贝对象的所有部分
1.默认构造函数介绍在设计良好的面向对象系统中,会将对象的内部进行封装,只有两个函数可以拷贝对象:拷贝构造函数和拷贝赋值运算符。我们把这两个函数统一叫做拷贝函数。从Item5中,我们得知,如果需要的话编译器会为你生成这两个拷贝函数,并且编译器生成的版本能够精确的做到你想做的:它们拷贝了对象的所有数据。2.自己实现构造函数有可能出现问题 当你声明自己的拷贝函数的时候,你就会向编译器表示,...原创 2017-02-17 07:42:00 · 176 阅读 · 1 评论 -
读书笔记 effective c++ Item 13 用对象来管理资源
1.不要手动释放从函数返回的堆资源假设你正在处理一个模拟Investment的程序库,不同的Investmetn类型从Investment基类继承而来,1 class Investment { ... }; // root class of hierarchy of2 3 // investment types进一步假设这个程序库通过一个工厂函数(Item 7)来给我们提供特定I...原创 2017-02-18 07:56:00 · 150 阅读 · 0 评论 -
读书笔记 effective c++ Item 14 对资源管理类的拷贝行为要谨慎
1. 自己实现一个资源管理类 Item 13中介绍了 “资源获取之时也是初始化之时(RAII)”的概念,这个概念被当作资源管理类的“脊柱“,也描述了auto_ptr和tr1::shared_ptr是如何用堆资源来表现这个概念的。然而并不是所有资源都是在堆上创建的,对于这种资源,像auto_ptr和tr1::shared_ptr这样的智能指针就不适合当作资源句柄(handle)来使用了。你会发现...原创 2017-02-19 09:32:00 · 146 阅读 · 0 评论 -
读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
1.为什么需要访问资源管理类中的原生资源 资源管理类是很奇妙的。它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征。在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不要直接访问原生(raw)资源而玷污你的双手。但是世界不是完美的,许多API会直接引用资源,所以除非你放弃使用这样的API(这是不实际的想法),你将会绕开资源管理类而时不时的处理原生资源。2. 如...原创 2017-02-20 07:20:00 · 155 阅读 · 0 评论 -
读书笔记 effective c++ Item 16 成对使用new和delete时要用相同的形式
1. 一个错误释放内存的例子下面的场景会有什么错?1 std::string *stringArray = new std::string[100];2 3 ...4 5 delete stringArray 一切看上去都是有序的。new匹配了一个delete。但有一些地方确实是错了。程序的行为是未定义的。至少来说,stringArray指向的100个string对象中的...原创 2017-02-21 08:05:00 · 107 阅读 · 0 评论 -
读书笔记 effective c++ Item 17 使用单独语句将new出来的对象放入智能指针
1. 可能会出现资源泄漏的一种用法假设我们有一个获取进程优先权的函数,还有一个在动态分配的Widget对象上根据进程优先权进行一些操作的函数:1 int priority();2 3 void processWidget(std::tr1::shared_ptr<Widget> pw, int priority);注意这里使用了对象管理资源的用法(Item 13),p...原创 2017-02-22 08:05:00 · 149 阅读 · 0 评论 -
读书笔记 effective c++ Item 18 使接口容易被正确使用,不容易被误用
1. 什么样的接口才是好的接口C++中充斥着接口:函数接口,类接口,模板接口。每个接口都是客户同你的代码进行交互的一种方法。假设你正在面对的是一些“讲道理”的人员,这些客户尝试把工作做好,他们希望能够正确使用你的接口。在这种情况下,如果接口被误用,你的接口应该至少负一部分的责任。理想情况下,如果使用一个接口没有做到客户希望做到的,代码应该不能通过编译;如果代码通过了编译,那么它就能做到客户想要...原创 2017-02-23 08:00:00 · 142 阅读 · 0 评论 -
读书笔记 effective c++ Item 19 像设计类型(type)一样设计类
1. 你需要重视类的设计c++同其他面向对象编程语言一样,定义了一个新的类就相当于定义了一个新的类型(type),因此作为一个c++开发人员,大量时间会被花费在扩张你的类型系统上面。这意味着你不仅仅是一个类的设计者同时是一个类型设计者。重载函数和运算符,控制内存分配和释放,定义对象初始化和终结,这些都是你需要考虑的。因此你应该同语言设计者一样,它们将时间浪费在内建类型的设计上,你就应该对类的设...原创 2017-02-24 07:51:00 · 202 阅读 · 2 评论 -
读书笔记 effctive c++ Item 20 优先使用按const-引用传递(by-reference-to-const)而不是按值传递(by value)...
1. 按值传递参数会有效率问题默认情况下,C++向函数传入或者从函数传出对象都是按值传递(pass by value)(从C继承过来的典型特性)。除非你指定其他方式,函数参数会用实际参数值的拷贝进行初始化,函数调用者会获得函数返回值的一份拷贝。这些拷贝由对象的拷贝构造函数生成。这使得按值传递(pass-by-value)变成一项昂贵的操作。举个例子,考虑下面的类继承体系(Item 7):...原创 2017-02-25 07:53:00 · 188 阅读 · 1 评论 -
读书笔记 effective c++ Item 21 当你必须返回一个对象的时候,不要尝试返回引用...
1. 问题的提出:要求函数返回对象时,可以返回引用么?一旦程序员理解了按值传递有可能存在效率问题之后(Item 20),许多人都成了十字军战士,决心清除所有隐藏的按值传递所引起的开销。对纯净的按引用传递(不需要额外的构造或者析构)的追求丝毫没有懈怠,但他们的始终如一会产生致命的错误:它们开始传递指向并不存在的对象的引用。这可不是好事情。考虑表示有理数的一个类,它包含将两个有理数相乘的函数(...原创 2017-02-26 19:06:00 · 141 阅读 · 0 评论 -
读书笔记 effective c++ Item 22 将数据成员声明成private
我们首先看一下为什么数据成员不应该是public的,然后我们将会看到应用在public数据成员上的论证同样适用于protected成员。最后够得出结论:数据成员应该是private的。1. 为什么数据成员不能是public的?为什么数据成员不能够是public的?2.1 一致性让我们从句法的一致性开始(Item 18)。如果数据成员不是Public的,那么客户访问对象的唯一方法就是...原创 2017-02-27 08:03:00 · 107 阅读 · 0 评论 -
读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数...
1. 非成员非友元好还是成员函数好?想象一个表示web浏览器的类。这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: 1 class WebBrowser { 2 3 public: 4 5 ... 6 7 void clearCache(); 8 9 void clearHistory();10 11 void r...原创 2017-02-28 08:31:00 · 223 阅读 · 0 评论 -
读书笔记 effective c++ Item 24 如果函数的所有参数都需要类型转换,将其声明成非成员函数...
1. 将需要隐式类型转换的函数声明为成员函数会出现问题使类支持隐式转换是一个坏的想法。当然也有例外的情况,最常见的一个例子就是数值类型。举个例子,如果你设计一个表示有理数的类,允许从整型到有理数的隐式转换应该是合理的。在C++内建类型中,从int转换到double也是再合理不过的了(比从double转换到int更加合理)。看下面的例子: 1 class Rational { 2 3...原创 2017-03-01 08:14:00 · 133 阅读 · 0 评论 -
读书笔记 effective c++ Item 25 实现一个不抛出异常的swap
1. swap如此重要Swap是一个非常有趣的函数,最初作为STL的一部分来介绍,它已然变成了异常安全编程的中流砥柱(Item 29),也是在拷贝中应对自我赋值的一种普通机制(Item 11)。Swap非常有用,恰当的实现swap是非常重要的,与重要性伴随而来的是一些并发症。在这个条款中,我们将探索这些并发症以及如何处理它们。2. swap的傻瓜实现方式及缺陷2.1 swap函数的默认...原创 2017-03-02 21:36:00 · 154 阅读 · 0 评论 -
读书笔记 effective c++ Item 26 尽量推迟变量的定义
1. 定义变量会引发构造和析构开销每当你定义一种类型的变量时:当控制流到达变量的定义点时,你引入了调用构造函数的开销,当离开变量的作用域之后,你引入了调用析构函数的开销。对未使用到的变量同样会产生开销,因此对这种定义要尽可能的避免。2. 普通函数中的变量定义推迟2.1 变量有可能不会被使用到的例子你可能会想你永远不会定义未使用的变量,你可能要再考虑考虑。看下面的函数,此函数返回pa...原创 2017-03-03 19:17:00 · 163 阅读 · 0 评论 -
读书笔记 effective c++ Item 27 尽量少使用转型(casting)
C++设计的规则是用来保证使类型相关的错误不再可能出现。理论上来说,如果你的程序能够很干净的通过编译,它就不会尝试在任何对象上执行任何不安全或无意义的操作。这个保证很有价值,不要轻易放弃它。不幸的是,casts颠覆了类型系统。它导致了各种麻烦的出现,一些很容易识别,一些却很狡猾(不容易被识别)。如果你以前使用过C,java或者C#,你就需要注意了,因为在这些语言中casting是更加必不...原创 2017-03-04 10:20:00 · 245 阅读 · 0 评论 -
读书笔记 effective c++ Item 28 不要返回指向对象内部数据(internals)的句柄(handles)...
假设你正在操作一个Rectangle类。每个矩形可以通过左上角的点和右下角的点来表示。为了保证一个Rectangle对象尽可能小,你可能决定不把定义矩形范围的点存储在Rectangle类中,而是把它放入一个辅助结构体中,Rectangle中声明一个指向它的指针就可以了: 1 class Point { // class for rep...原创 2017-03-06 23:27:00 · 158 阅读 · 0 评论 -
读书笔记 effective c++ Item 29 为异常安全的代码而努力
异常安全在某种意义上来说就像怀孕。。。但是稍微想一想。在没有求婚之前我们不能真正的讨论生殖问题。假设我们有一个表示GUI菜单的类,这个GUI菜单有背景图片。这个类将被使用在多线程环境中,所以需要mutex进行并发控制。 1 class PrettyMenu { 2 public: 3 ... 4 void changeBackground(std::istream& ...原创 2017-03-07 21:14:00 · 174 阅读 · 0 评论 -
读书笔记 effective c++ Item 30 理解内联的里里外外 (大师入场啦)
最近北京房价蹭蹭猛涨,买了房子的人心花怒放,没买的人心惊肉跳,咬牙切齿,楼主作为北漂无房一族,着实又亚历山大了一把,这些天晚上睡觉总是很难入睡,即使入睡,也是浮梦连篇,即使亚历山大,对C++的热情和追求还是不减,应该是感动了周公吧,梦境从此处开始,大师入场来给我安慰了。。。11点躺在床上了,脑子里总结一下最近的工作:最近的开发用到inline函数比较多,众所周知,inline的使用是为了提高程...原创 2017-03-08 21:36:00 · 157 阅读 · 0 评论 -
读书笔记 effective c++ Item 31 把文件之间的编译依赖降到最低
1. 牵一发而动全身现在开始进入你的C++程序,你对你的类实现做了一个很小的改动。注意,不是接口,只是实现,而且是private部分。然后你需要rebuild你的程序,计算着这个build应该几秒钟就足够了。毕竟,只修改了一个类。你点击了build 或者输入了make( 或者其他方式),你被惊到了,然后羞愧难当,因为你意识到整个世界都被重新编译和重新链接了!当这些发生时你不觉的感到愤恨么...原创 2017-03-12 16:25:00 · 156 阅读 · 0 评论 -
读书笔记 effective c++ Item 32 确保public继承建立“is-a”模型
1. 何为public继承的”is-a”关系在C++面向对象准则中最重要的准则是:public继承意味着“is-a”。记住这个准则。如果你实现一个类D(derived)public继承自类B(base),你在告诉c++编译器(也在告诉代码阅读者),每个类型D的对象也是一个类型B的对象,反过来说是不对的。你正在诉说B比D表示了一个更为一般的概念,而D比B表现了一个更为特殊的概念。你在主...原创 2017-03-14 22:28:00 · 146 阅读 · 0 评论 -
读书笔记 effective C++ Item 33 避免隐藏继承而来的名字
1. 普通作用域中的隐藏名字实际上和继承没有关系。有关系的是作用域。我们都知道像下面的代码: 1 int x; // global variable 2 3 void someFunc() 4 { 5 double x; // local variable 6 7 std::cin >> x; /...原创 2017-03-15 20:56:00 · 192 阅读 · 0 评论 -
读书笔记 effective c++ Item 34 区分接口继承和实现继承
看上去最为简单的(public)继承的概念由两个单独部分组成:函数接口的继承和函数模板继承。这两种继承之间的区别同本书介绍部分讨论的函数声明和函数定义之间的区别完全对应。1. 类函数的三种实现作为一个类设计者,有时候你只想派生类继承成员函数的接口(声明)。有时候你想让派生类同时继承接口和实现,但是你允许它们覆盖掉继承而来的函数实现。但有时候你却想让派生类继承一个函数的接口和实现并且不...原创 2017-03-20 22:26:00 · 146 阅读 · 0 评论 -
读书笔记 effective c++ Item 35 考虑虚函数的替代者
1. 突破思维——不要将思维限定在面向对象方法上你正在制作一个视频游戏,你正在为游戏中的人物设计一个类继承体系。你的游戏处在农耕时代,人类很容易受伤或者说健康度降低。因此你决定为其提供一个成员函数,healthValue,返回一个整型值来表明一个人物的健康度。因为不同的人物会用不同的方式来计算健康度,将healthValue声明为虚函数看上去是一个比较明显的设计方式:1 class...原创 2017-03-23 21:47:00 · 243 阅读 · 2 评论 -
读书笔记 effective c++ Item 36 永远不要重新定义继承而来的非虚函数
1. 为什么不要重新定义继承而来的非虚函数——实际论证假设我告诉你一个类D public继承类B,在类B中定义了一个public成员函数mf。Mf的参数和返回类型并不重要,所以假设它们都是void。实现如下:1 class B {2 public:3 void mf();4 ...5 };6 lass D: public B { ... }我们不需要了解B,D或者mf...原创 2017-03-24 20:12:00 · 149 阅读 · 0 评论 -
读书笔记 effective c++ Item 37 永远不要重新定义继承而来的函数默认参数值
从一开始就让我们简化这次的讨论。你有两类你能够继承的函数:虚函数和非虚函数。然而,重新定义一个非虚函数总是错误的(Item 36),所以我们可以安全的把这个条款的讨论限定在继承带默认参数值的虚函数上。1. 虚函数是动态绑定的,而默认参数是静态绑定的在这种情况下,这个条款的验证就相当直接了:虚函数是动态绑定的,而默认参数值是静态绑定的。这是什么?你说你不堪重负的脑袋已经忘记了动态绑...原创 2017-03-25 17:50:00 · 204 阅读 · 2 评论 -
读书笔记 effective c++ Item 38 通过组合(composition)为 “has-a”或者“is-implemented-in-terms-of”建模...
1. 什么是组合(composition)?组合(composition)是一种类型之间的关系,这种关系当一种类型的对象包含另外一种类型的对象时就会产生。举个例子: 1 class Address { ... }; // where someone lives 2 3 class PhoneNumber { ... }; 4 class Person { ...原创 2017-03-27 20:36:00 · 208 阅读 · 0 评论 -
读书笔记 effective c++ Item 39 明智而谨慎的使用private继承
1. private 继承介绍Item 32表明C++把public继承当作”is-a”关系来对待。考虑一个继承体系,一个类Student public 继承自类Person,如果一个函数的成功调用需要从Student到Person的隐式转换,这时候“is-a”关系就出现了。对于一部分实例,使用private继承来代替public继承也是有价值的事情: 1 class Person { ...原创 2017-03-28 21:14:00 · 203 阅读 · 0 评论 -
读书笔记 effective C++ Item 40 明智而谨慎的使用多继承
1. 多继承的两个阵营当我们谈论到多继承(MI)的时候,C++委员会被分为两个基本阵营。一个阵营相信如果单继承是好的C++性质,那么多继承肯定会更好。另外一个阵营则争辩道单继承诚然是好的,但多继承太麻烦,而不值得去使用它。在这个条款中,我的主要目标是让你明白多继承的这两个观点。2. 从多个基类中继承的名字不能相同第一件事情是你需要认识到使用MI进行设计时,从多个基类中可能会继承相同的名...原创 2017-03-29 21:23:00 · 211 阅读 · 0 评论