![](https://img-blog.csdnimg.cn/20190927151026427.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
EffectiveC++
文章平均质量分 68
EffectiveC++
@Moota
文章仅作闲的很闲的学习记录,不想咸鱼就快跑!!!
展开
-
EffectiveC++-读后感
## 一. 内容1. 正如序言所说,`这是一本讲 C++ 语言特性和编程技巧的书`,对于想要进一步学习 C++ 的同学来说,是不可多得的好书,如果对此有深入的兴趣,看完的同学可以试试作者的另外两本书:《More Effective C++》和《Effective STL》,同样是讲规范,讲准则,讲高效做法的书籍,值得一试。2. 从考试结束后,不算之前零碎的时间,共计 `21` 天完成所有条款的学习和笔记,其中前 `7` 天完成书籍的阅读和笔记,后 `14` 天 完成博客的摘录和代码的测试。初次体会到:一原创 2022-07-24 20:23:42 · 329 阅读 · 0 评论 -
EffectiveC++-条款55:让自己熟悉 Boost
## 一. 内容1. 你正在寻找一个`高质量,源码开放,平台独立,编译期独立的程序库`吗?看看 Boost 吧。有兴趣加入一个由雄心勃勃,充满才干的 C++ 开发人员组成的社群,`致力发展当前最高技术水平的程序库`吗?看看 Boost 吧。想要一瞥未来 C++ 的面目吗?看看 Boost 吧。2. `Boost 委员会和 C++ 标准委员会成员有很密切的关系`,并对其有着深刻的影响能力。Boost 由标准委员会创立,因此两者成员有着很大重叠。Boost 有个目标:作为一个可被加入到标准 C++ 的功能测原创 2022-07-24 19:21:30 · 202 阅读 · 0 评论 -
EffectiveC++-条款54:让自己熟悉包括TR1在内的标准程序库
## 一. 内容1. 新版本的 C++ 或许会具有某些新的有趣特性,但大部分新机能都是以标准程序库的扩充形式体现。如果我们不了解相关的信息,就很难成为一位高效的 C++ 程序员。 2. `C++ 98 的标准程序库成分`: - STL(Standard Template Library,标准模板库),覆盖容器(containers 如 vector,string,map),迭代器(iterators),算法(algorithm 如 find,sort,transform),函数对象(function原创 2022-07-24 18:43:12 · 279 阅读 · 0 评论 -
EffectiveC++-条款53:不要轻忽编译器的警告
## 一. 内容1. `许多程序员习惯性的忽略编辑器警告`。它们认为:毕竟,如果问题很严重,编译器应该给一个错误信息而非警告信息,不是吗?2. 我们看一个例子: ```cpp int a=1; if (a=1) { std::cout.........原创 2022-07-24 17:29:11 · 416 阅读 · 0 评论 -
EffectiveC++-条款52:写了 placement new 也要写 placement delete
## 一. 内容1. `placement new` 和 `placement delete` 在 C++ 中并不常见,如果不熟悉它们,不要感到害怕和忧虑。2. 回忆条款16和17,当你写一个 new 表达式时: ```cpp FString *String = new FString("HelloWorld"); ``` 共有两个函数被调用:一个是用以分配内存的 operator new,一个是 FString 的构造函数。 假如第一个函数调用成功,第二个函数却抛出异常。那么运行期系统原创 2022-07-24 17:11:59 · 149 阅读 · 0 评论 -
EffectiveC++-条款51:编写 new 和 delete 时需固守常规
## 一. 内容1. 条款50已经解释了什么时候你需要写个自定义的 new 和 delete,但没有解释你编写时应该遵守什么样的规则,接下来我们将介绍其中的规则:2. 对于 operator new: - operator new 的返回值很简单。如果它有能力供应客户申请的内存,就返回一个指针指向那块内存。如果没那个能力,就遵循条款49描述的规则,并抛出 bad_alloc 异常。 - C++ 规定,即使客户要求 0 bytes,operator new也得返回一个合法指针。常用的做法是将 0 by原创 2022-07-24 11:46:34 · 275 阅读 · 0 评论 -
EffectiveC++-条款50:了解 new 和 delete 的合理替换时机
## 一. 内容1. 怎么会有人想要替换编译器提供的 operator new 或 operator delete 呢?以下是七个常见的理由: - 用来`检测运用上的错误`。 当将 new 所得内存 delete 失败时,会导致内存泄漏。当在 new 所得内存 多次 delete 时,会导致未定义行为。如果自定义 new 或者 delete,就很容易检测出这类错误。此外,各式各样的编程错误,可能导致数据越界,超出已分配的内存,包括上溢(over-runs)和下溢(under-runs)。如果使用原创 2022-07-23 20:16:59 · 204 阅读 · 0 评论 -
EffectiveC++-条款49:了解 new-handler 行为
## 一. 内容1. 当你调用 operator new 函数,程序无法满足某一内存需求时,它会抛出异常。老旧的编译器会返回 null 指针。而抛出异常之前,程序会先调用一个 operator new 错误处理函数,名叫 `new-handler`。 `new-handler 是一个 typedef,指向一个无参数值无返回值的函数`。我们可以通过 set_new_handler 函数去指定客户想要的 new-handler。 `set_new_handler 函数接受一个新的 new-handle原创 2022-07-23 17:53:54 · 245 阅读 · 0 评论 -
EffectiveC++-条款48:认识 template 元编程
## 一. 内容1. template metaprogramming(TMP)模板元编程使编写 template C++ 程序并执行于编译期的过程。所谓模板元程序就是:以 C++ 写成,执行于 C++ 编译器内的程序。该程序执行后产生具现的代码,和正常代码一并加入编译。也就说`元编程`可以做到`用代码去生成代码`。2. TMP 伟大之处在于,由于 template metaprograms 执行于 C++ 编译期,因此可以`将很多工作从运行期转移到编译期`。例如: - 某些错误原本通常在运行期才原创 2022-07-23 16:20:59 · 234 阅读 · 0 评论 -
EffectiveC++-条款47:请使用 traits classes 表现类型信息
## 一. 内容1. 本条款仍然以例子入手,假如你要设计`一个 Move 函数,用于将 STL 的迭代器移动指定的距离`: ```cpp template void Move(IteratorType & Iterator,int Distance);`在这里插入代码片` ```2. 我们先来认识一下 STL 迭代器的分类,迭代器共有 5 种类型: - Input 迭代器,只能一步一步向前移动,只能读取内容,且仅读取一次。 - Output...............原创 2022-07-22 21:18:11 · 291 阅读 · 0 评论 -
EffectiveC++-条款46:需要类型转换时请为模板定义非成员函数
## 一. 内容1. 条款24讨论了为什么只有 non-member 函数才有能力在所有实参身上实施隐式类型转换。在本条款下,我们将讨论的范围`扩展到 template 的领域`: ```cpp template class TRational { public: TRational(const T& mNumerator, const T& mDenominator): Numerator(mNumerator), Denominator.........原创 2022-07-22 17:48:23 · 198 阅读 · 0 评论 -
EffectiveC++-条款45:运用成员函数模板接受所有兼容类型
## 一. 内容1. 我们从例子入手,所谓智能指针(smart pointer),是行为像指针的对象,并提供指针没有的机能:自动管理资源。但原始指针(raw pointer)做的很好的一件事是:支持隐式转换(implicit conversions)。比如 derived class 指针可以隐式转换为 base class 指针,指向 non-const 的指针可以转换为 指向 const 的指针... 而对于 template 具现的类,并不能很好的进行像原始指针一样的隐式转换,比如想把一个具现类原创 2022-07-22 15:37:01 · 179 阅读 · 0 评论 -
EffectiveC++-条款44:将与参数无关的代码抽离 templates
## 一. 内容1. `templates 是节省时间和避免代码重复的奇方妙法。`你不再需要键入 20 个类似的 classes 并且每一个都带有 20 个 成员函数,你只需要键入一个 class template,留给编译器去具现化那 20 个你需要的相关 classes 即可,而且对于 20 个函数中未被调用的,编译器不会自动生成。这样的技术是不是很伟大,呵呵。2. 但是,这也很容易使得代码膨胀(code bloat),templates 产出码带着重复,或者几乎重复的代码,数据,或者两者。你可以通原创 2022-07-22 10:49:52 · 369 阅读 · 0 评论 -
EffectiveC++-条款43:学习处理模板化基类内的名称
## 一. 内容1. 我们从一个例子入手,假设我们要设计游戏中人物的相关列表,比如 buff 列表,物品列表等等,一个显而易见的设计是: ```cpp class Buff { public: virtual ~Buff() = default; virtual void Start() =0; virtual void End() =0; virtual void OnTick() =0; }; class RedBuff : public Buf原创 2022-07-21 19:57:08 · 219 阅读 · 0 评论 -
EffectiveC++-条款42:了解 typename 的双重意义
## 一. 内容1. 提一个问题,以下 template 声明式中,class 和 typename 有什么不同? ```cpp template class Demo; template class Demo; ``` 答案:没有不同。`当我们声明 template 类型参数时, class 和 typename 的意义完全相同`。 某些程序员喜欢 class,因为可以少打几个字。 其他人,包括我,比较喜欢 typename ,...原创 2022-07-21 15:35:39 · 136 阅读 · 0 评论 -
EffectiveC++-条款41:了解隐式接口和编译器多态
## 一. 内容1. 面向对象的世界总是以显式接口和运行期多态解决问题。举个 Widget 的例子: ```cpp class Widget { public: virtual ~Widget()=default; virtual void Normalize()=0; }; class SpecialWidget:public Widget { public: virtual void Normalize() override { std::原创 2022-07-21 10:31:17 · 311 阅读 · 0 评论 -
EffectiveC++-条款40:明智而审慎地使用多重继承
## 一. 内容1. 一旦涉及多重继承,C++社群便分为两个基本阵营。其中之一认为:如果单一继承是好的,多重继承一定更好。另一阵营认为:单一继承是好的,但多重继承不值得拥有。本条款主要目的是让大家了解这两个多重继承的基本观点。2. 最先要认清的一件事是:使用多重继承会导致 class 可能从一个以上的 base class 继承相同名称(如函数,变量,typedefs等),那会导致较多的歧义。C++在解析重载函数调用时,会先查找是否具有对此调用匹配的函数,找出最佳匹配后再检验其可取性。这意味着即使在 b原创 2022-07-20 15:45:52 · 164 阅读 · 0 评论 -
EffectiveC++-条款39:明智而审慎地使用 private 继承
## 一. 内容1. 对于 public 继承,条款32曾论证过是 is-a 关系。而对于 private 继承,显然并不是 is-a 的关系。2. 我们先看看 private 继承的意义 - 如果 derived class 和 base class 是 private 继承,那么从 derived class 到 base class 的转换将失败。 - 由 private base class 继承而来的所有成员,在 derived class 中访问权限都将变为 private。.....原创 2022-07-20 12:01:58 · 405 阅读 · 0 评论 -
EffectiveC++-条款38:通过复合塑模出 has-a 或 根据某物实现出
## 一. 内容1. 在程序员之间复合(composition)有很多同义词,包括 layering(分层),containment(内含),aggregation(聚合)和 embedding(内嵌)。2. 复合(composition)是类型之间的一种关系:当某种类型的对象内含其他类型的对象。举例,一个人可以有名字,有地址,有手机号码: ```cpp class Address; class PhoneNumber; class Person { public: //...原创 2022-07-20 10:08:48 · 648 阅读 · 0 评论 -
EffectiveC++-条款37:绝不重新定义继承而来的缺省参数值
## 一. 内容1. 让我们一开始就将讨论简化,你只能继承两种函数:virtual 和 non-virtual 函数。而条款36刚刚讲述到:重新定义一个继承而来的 non-virtual 函数永远是错误的。因此我们可以将眼光局限在:继承一个带有缺省参数值的 virtual 函数。2. 这种情况下,本条款成立的理由就显而易见了:virtual 函数是动态绑定,但是缺省参数值却是静态绑定。3. 先容我介绍下,静态绑定和动态绑定的差异。对象的所谓静态类型(static type),就是它在程序中被声明时采用原创 2022-07-18 18:03:13 · 177 阅读 · 0 评论 -
EffectiveC++-条款36:绝不重新定义继承而来的 non-virtual 函数
## 一. 内容1. 考虑以下示例,一个 D class 继承自 B class 的体系中,两者均定义了同样的 non-virtual 函数: ```cpp class B { public: std::string ToString() const{ return "B"; } }; class D : public B { public: std::string ToString() const{ return "D"原创 2022-07-18 17:15:52 · 160 阅读 · 0 评论 -
EffectiveC++-条款35:考虑 virtual 函数以外的其他选择
## 一. 内容1. 本条款以举例入题,假如你在设计一款游戏,涉及到各式角色的健康情况,但不同角色的健康度是不同的,这时候将计算健康度的函数声明为 virtual 似乎是再明白不过的做法: ```cpp class Character { public: virtual ~Character()=default; virtual int CalculateHealthValue() const; }; class NpcEvil:public Character {原创 2022-07-18 12:14:14 · 279 阅读 · 0 评论 -
EffectiveC++-条款34:区分接口继承和实现继承
## 一. 内容1. 仔细思考,public 继承其实可以分成:函数接口(function interfaces)继承和函数实现(function implemention)继承。这意味着 derived class 不仅可以有 base class 函数的声明,还可以有 base class 函数的实现。2. 作为 class 的设计者,有时候你会希望 derived class 只继承成员函数的接口,也就是声明;有时候你又会希望 同时继承函数的接口和实现,但又允许覆写(override)它们继承的实原创 2022-07-17 20:12:33 · 183 阅读 · 0 评论 -
EffectiveC++-条款33:避免遮掩继承而来的名称
## 一. 内容1. 这个主题其实与作用域(Scope)有关。举个例子: ```cpp int x=1; //全局变量 void func() { double x=1.1; //局部变量 std::cout原创 2022-07-17 17:24:43 · 256 阅读 · 0 评论 -
EffectiveC++-条款32:确定你的 public 继承塑模出 is-a 关系
## 一. 内容1. 以C++进行面向对象编程,最重要的一个规则是:public inheritance (公开继承)意味着 is-a 的关系,请把这个规则牢牢记在心中。2. 也就是说,如果你令 class D 以 public 的方式继承 class B,你便是告诉C++编译器和你的客户:每一个类型为 D 的对象,同时也是一个类型为 B的对象,反之则不成立。类型 B 比 类型 D 表现出更一般的概念,而类型 D 比类型 B 表现出更特殊化的概念。B 对象可使用到的地方,D 对象都可以派上用场。反之,原创 2022-07-17 16:24:48 · 139 阅读 · 0 评论 -
EffectiveC++-条款31:将文件间的编译依存关系降至最低
## 一. 内容1. 假如你对C++程序的某个class实现做了轻微修改,仅仅只是修改了private接口,然后重新构建这个程序。当你以为只要数秒就能完成的事:毕竟只有一个class被修改。但当你按下 build 类似按钮后,你意识到整个世界都被重新编译和连接了!发生这样的事,难道你不气恼吗?2. 问题出在:C++并没有把接口从实现中分离这件事做的很好。比如你在头文件定义了一些类成员变量,非指针或者引用,编译器就需要其定义式。而这样的定义式通常由 #include 指示符提供。所以你可能会 #inclu原创 2022-07-15 21:47:41 · 591 阅读 · 0 评论 -
EffectiveC++-条款30:透彻了解 inlining 的里里外外
## 一. 内容1. inline 函数,多棒的点子!它们看起来像函数,动作像函数,比宏好用的多,见条款2,可以调用它们又不需花费因调用函数带来的额外开销。而且编译器最优化机制通常被设计来优化那些不含函数调用的代码,这意味编译器有能力对 inline 函数做语境相关的最优化。2. 然后编写程序就像现实生活一样,没有白吃的午餐,inline函数也不例外。inline 函数背后的机制是:将对此函数的每一个调用都用函数本体替换之。这样无疑会增加产出码的大小,在一台内存有限的机器上,过度热衷 inline 机制原创 2022-07-15 10:19:46 · 187 阅读 · 0 评论 -
EffectiveC++-条款29:为异常安全而努力是值得的
## 一. 内容1. 异常安全有两个条件,当异常被抛出时,带有异常安全的函数会: - 不泄漏任何资源 - 不允许数据败坏2. 异常安全函数提供以下三个保证之一: - 基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态之下。没有任何对象或者数据结构因此被破坏。 - 强烈保证:如果异常被抛出,程序状态不改变。调用这样的函数有这样的认知:如果函数成功,就是完全成功,如果函数失败,程序状态会回到调用函数之前的状态。 - 不抛掷保证:承诺绝不抛出任何异常,因为它们总是能够完成它们原先承诺的功能原创 2022-07-14 21:18:49 · 228 阅读 · 0 评论 -
EffectiveC++-条款28:避免返回 handles 指向对象内部成分
## 一. 内容1. 举个例子,假如你的程序涉及矩形,每个矩形由左上角和右下角坐标表示,然后采用 pimpl 手法,以及之前学过的条款知识。 ```cpp namespace RectangleStuff { class Point { public: Point(int mX, int mY): X(mX), Y(mY) {} public: void SetX(int mX) { X = mX;原创 2022-07-14 20:51:33 · 251 阅读 · 0 评论 -
EffectiveC++-条款27:尽量少做转型动作
## 一. 内容1. C++规则的设计目标之一是,保证类型错误绝不可能发生。理论上如果你的代码很干净的通过编译,就表示它并不企图在任何对象身上执行任何不安全的,无意义的,荒谬的操作。你应该始终坚持这一点。2. 不幸的是,转型破坏了类型系统,这可能导致任何种类的错误,有些容易识别,有些则相当隐晦。3. 我们先回顾转型语法。C风格的转型:(T)expression。函数风格的转型:T(expression)。两种形式并无差别,纯粹只是小括号摆放位置不一样而已,这是旧式转型。C++还提供四种新型转型,常常被原创 2022-07-14 19:38:39 · 220 阅读 · 0 评论 -
EffectiveC++-条款26:尽可能延后变量定义式的出现时间
## 一. 内容1. 大多数情况下,适当提出你的classes定义和function声明,是花费心力最多的两件事。一旦正确完成它们,相应的实现大多直接了当。但是还有有些东西需要注意,我们将在之后的条款一一描述。2. 只要你定义了一个变量而其类型带有一个构造函数或析构函数,当程序执行到这个变量定义式时,你便得承受构造成本,当这个变量离开作用域时,你便得承受析构成本。即使这个变量并未使用。3. 或许你认为你不会定义一个不使用的变量,但话不要说的太早。 ```cpp class Password {原创 2022-07-14 18:36:36 · 203 阅读 · 0 评论 -
EffectiveC++-条款25:考虑写出一个不抛异常的 swap 函数
## 一. 内容1. swap 是一个有趣的函数。原本它只是STL的一部分,后面成为异常安全性编程的重要支柱(见条款29),以及处理自我赋值的常见机制(见条款11)。swap如此有用,考虑其合理的实现变得十分重要。2. 所谓 swap(置换),就是将两个对象的值彼此赋值给对方。3. 默认情况下,swap 可以交给 标准程序库提供的 swap 算法完成,其典型实现正如预期。 ```cpp namespace std{ template void swap(............原创 2022-07-14 12:27:44 · 226 阅读 · 0 评论 -
EffectiveC++-条款24:若所有参数皆需类型转换,请为此采用 non-member函数
## 一. 内容1. 在导读中提过,令classes支持隐式转换是一个糟糕的主意,当然这有例外。比如当你建立一个数值类型,允许整数隐式转换为有理数似乎是合理的。好比C++允许int隐式转换为double,double隐式转换为int。2. 举个例子,假如你要编写一个分数Rational类。 ```cpp class Rational { public: Rational(int mNumerator = 0, int mDenominator = 1): Numerat原创 2022-07-14 11:14:18 · 175 阅读 · 0 评论 -
EffectiveC++-条款23:宁以 non-member、non-friend 替换 member函数
## 一. 内容1. 举个例子,当你有个class表示浏览器时,有众多功能需要提供,其中可能有清除下载元素的高速缓存区,清除访问过的URLs,清除系统中所有的cookies。示例代码 ```cpp class WebBrowser { public: void ClearCache(){std::cout............原创 2022-07-14 10:16:10 · 199 阅读 · 0 评论 -
EffectiveC++-条款22:将成员变量声明为 private
## 一. 内容1. 为什么不推荐编写public成员变量呢? - 从语法一致性开始,如果成员变量不是public,唯一能访问对象的方式就是通过成员函数,如果public中每一样都是函数,那么客户就不必记住访问成员时记住究竟是否使用小括号,这样可以节省很多开发时间。 - 使用函数访问而不是直接访问可以对成员变量有更精确的控制。如果你令成员变量为public,那么每个人都可以读写它而不受限制,函数则不同,利用函数设置和获取值,你可以实现不准访问,只读访问,读写访问,只写访问。 当然,不必对每一个原创 2022-07-14 09:35:59 · 159 阅读 · 0 评论 -
EffectiveC++-条款21:必须返回对象时,别妄想返回其reference
## 一. 内容1. 一旦程序员领悟到 pass-by-value 的效率问题,往往变成十字军战士,一心一意根除 pass-by-value带来的种种邪恶。但追求 pass-by-reference 的纯度时,可能会犯这样一个错误:开始传递一些 reference 指向不存在的对象。2. 记住 reference 只是一个名称,代表某个既有对象。任何时候看到一个 reference 申明式,你都应该问自己它的另外一个名称是什么?因为它一定是指向某个既有的对象。3. 函数可以在stack空间创建新对象原创 2022-07-13 18:02:29 · 209 阅读 · 0 评论 -
EffectiveC++-条款20:宁以 pass-by-reference-to-const 替换 pass-by-value
## 一. 内容1. 默认情况下C++以by value的方式传递对象至(或来自)函数。而传值的方式需要调用对象的拷贝构造函数,如果拷贝的代价是昂贵的,无疑会降低代码运行效率。2. 在函数中以值传递对象时,需要创建临时对象,那么在对象的生成和销毁需要分别调用构造函数和析构函数,这也大大增加了传值的代价。3. 怎么回避这些默认的行为呢?以常引用的方式进行传递。使用引用不会有任何构造函数和析构函数被调用,常量性保证了函数不会对传入的参数做任何更改。4. 以by reference 传递参数的方式也避免了原创 2022-07-13 17:31:21 · 166 阅读 · 0 评论 -
EffectiveC++-条款19:设计 class 犹如设计 type
## 一. 内容1. C++就像其他OOP(面向对象编程)语言一样,当你定义一个新class,也就新定义了一个type。这意味你不仅是class设计者,还是type设计者。重载函数和操作符,控制内存的分配和归还,定义对象的初始化和销毁...全都在你手上。因此我们应该带着和语言设计者当初设计内置类型时,一样的谨慎来研讨class的设计。2. 如果设计高效的class?以下是一些问题: - 新type的对象应该如何被创建和销毁?这会影响到构造函数和析构函数,内存分配函数和释放函数(Operator new原创 2022-07-13 17:02:40 · 141 阅读 · 0 评论 -
EffectiveC++-条款18:让接口容易被正确使用,不易被误用
## 一. 内容1. 准则:如果客户使用某个接口通过了编译,那么它的行为就是应该是客户想要的。2. 所以我们应该考虑客户可能会遇到什么样的错误。3. 一个例子 ```cpp class Date { public: Date(int mMonth,int mDay,int mYear): Month(mMonth),Day(mDay),Year(mYear){} private: int Month; int Day; int Year; }原创 2022-07-13 16:39:32 · 213 阅读 · 0 评论 -
EffectiveC++-条款17:以独立语句将newed对象置入智能指针
## 一. 内容1. 令人惊讶的是,即使我们使用对象管理资源,下面代码仍存在泄漏资源。 ```cpp inline Resource* GetResource() { return new Resource(1); } inline void OtherProgress(std::shared_ptr Resource, int Priority) {} inline void UseResource() { OtherProgress(std::s..........原创 2022-07-13 15:52:53 · 243 阅读 · 0 评论