【Effective C++ 第三版】系列总览:55 个条款 × 11 篇文章,Scott Meyers 经典精读

一句话核心结论:《Effective C++》第三版是 C++ 程序员书架上的”圣经级”读物——它用 55 个条款,把”什么样的 C++ 代码才算专业”这件事讲透了。读完之后,你看 constvirtualoperator=template 这些基础语法的眼神,都会变。


一、前言:为什么 2026 年还要读《Effective C++》?

很多人觉得这本书”过时了”——它基于 C++98/03 标准,没有 C++11/14/17/20 的新特性。

错得离谱。

《Effective C++》第三版(2005 年出版)讨论的不是某个版本的语法,而是C++ 编程的本质规律

表面上看实质上在讲
条款 03:尽量使用 const编译器帮你把”不变性”做实,能挡掉一半的 bug
条款 13:以对象管理资源RAII 是 C++ 区别于 C/Java 的核心范式
条款 25:考虑写一个不抛异常的 swap函数设计要”正交”,可组合性来自接口设计
条款 41:了解隐式接口和编译期多态模板元编程的底层思维
条款 47:请使用 traits classes 表现类型信息这就是 <type_traits> 库的前身

这些条款对新特性同样适用——std::unique_ptr 完美符合条款 13,C++20 concepts 完美符合条款 41/47。即便你只用 C++17/20,把这 55 条内化,代码质量也会跨一个台阶。

1.1 读完这个系列你能得到什么?

你将获得具体形式
C++ 编程的”宪法”55 条条款逐条解读,每条配实战代码
三大核心范式RAII / 接口设计 / 模板元编程 的完整方法论
避坑地图经典 C++ 坑(拷贝控制、虚析构、对象切片)的 200+ 反例
新特性桥梁条款 13 → unique_ptr、条款 28 → std::clamp、条款 47 → concepts
思维升级从”会写 C++”到”写出地道的 C++”

1.2 这个系列适合谁?

  • C++ 初学者:刚看完《C++ Primer》,想从”语法层”跃迁到”工程层”
  • 3~5 年经验工程师:希望系统化整理”我凭什么写得好”
  • C++ 面试候选人:80% 的 C++ 面试题都源自这 55 个条款
  • 转型者:从 Java/Go/Python 转 C++,需要建立 C++ 的工程直觉
  • 技术 Leader:希望团队代码风格统一、有据可依

二、55 个条款的 9 大主题全景

我把 55 个条款归类到 9 大主题,形成一棵知识树。

graph TB
    ROOT["🦄 Effective C++ 知识体系\n55 个条款 × 11 篇文章"]

    T1["🟣 让自己习惯 C++\n条款 1-4(4 条)"]
    T2["🟢 构造/析构/赋值\n条款 5-12(8 条)"]
    T3["🔵 资源管理\n条款 13-17(5 条)"]
    T4["🟡 设计与声明\n条款 18-25(8 条)"]
    T5["🟠 实现\n条款 26-31(6 条)"]
    T6["🔴 继承与面向对象\n条款 32-40(9 条)"]
    T7["🩷 模板与泛型\n条款 41-48(8 条)"]
    T8["⚫ 定制 new/delete\n条款 49-52(4 条)"]
    T9["⚪ 杂项讨论\n条款 53-55(3 条)"]

    ROOT --> T1
    ROOT --> T2
    ROOT --> T3
    ROOT --> T4
    ROOT --> T5
    ROOT --> T6
    ROOT --> T7
    ROOT --> T8
    ROOT --> T9

    style ROOT fill:#E8D5F5,stroke:#CE93D8,stroke-width:3px,color:#333
    style T1 fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style T2 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style T3 fill:#FFF9C4,stroke:#F9A825,color:#333
    style T4 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style T5 fill:#FFB3C6,stroke:#F48FB1,color:#333
    style T6 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style T7 fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style T8 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style T9 fill:#F5F5F5,stroke:#9E9E9E,color:#333

2.1 主题占比与难度分布

主题条款范围条款数推荐篇目难度占比
让自己习惯 C++01-044第 1 篇⭐⭐7%
构造/析构/赋值05-128第 2 篇⭐⭐⭐15%
资源管理13-175第 3 篇⭐⭐⭐9%
设计与声明18-258第 4、5 篇⭐⭐⭐15%
实现26-316第 6 篇⭐⭐⭐11%
继承与面向对象32-409第 7、8 篇⭐⭐⭐⭐16%
模板与泛型41-488第 9 篇⭐⭐⭐⭐15%
定制 new/delete49-524第 10 篇⭐⭐7%
杂项53-553第 11 篇⭐⭐5%

2.2 9 大主题的内在逻辑

graph LR
    A["🟣 基础哲学\n(让自己习惯 C++)"] --> B["🟢 类设计基础\n(构造/析构/赋值)"]
    B --> C["🟡 资源管理\n(RAII 范式)"]
    B --> D["🟠 接口设计\n(设计与声明)"]
    D --> E["🔴 继承体系\n(OOP 设计)"]
    D --> F["🟠 实现细节\n(实现)"]
    C --> G["⚫ 内存底层\n(定制 new/delete)"]
    D --> H["🩷 模板泛型\n(编译期多态)"]
    H --> I["⚪ 杂项\n(标准库/Boost)"]

    style A fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style B fill:#B5EAD7,stroke:#80CBC4,color:#333
    style C fill:#FFF9C4,stroke:#F9A825,color:#333
    style D fill:#FFDAB9,stroke:#FFAB76,color:#333
    style E fill:#E8D5F5,stroke:#CE93D8,color:#333
    style F fill:#FFB3C6,stroke:#F48FB1,color:#333
    style G fill:#B5EAD7,stroke:#80CBC4,color:#333
    style H fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style I fill:#F5F5F5,stroke:#9E9E9E,color:#333

关键观察

  1. 基础哲学 → 类设计 → 资源管理是一条主线:教你怎么把”对象生命周期”控制好
  2. 接口设计 → 继承 / 模板是另一条主线:教你怎么设计”可复用的契约”
  3. **内存底层(条款 49-52)**是性能优化的”逃生舱口”,90% 的项目用不到
  4. **杂项(条款 53-55)**虽是短篇,但 55 条 “熟悉 Boost” 是 Scott Meyers 给 C++ 社区的”开眼看世界”

三、11 篇目录:完整篇目与阅读时长

下表是 11 篇文章的目录。每篇约 15 分钟阅读,覆盖约 5~8 个条款。

篇号文章标题条款数难度时长
第 1 篇让自己习惯 C++:视 C++ 为语言联邦1-4⭐⭐15 min
第 2 篇构造/析构/赋值:对象生命周期的 5 把钥匙5-12⭐⭐⭐18 min
第 3 篇资源管理:RAII 范式与智能指针13-17⭐⭐⭐16 min
第 4 篇设计与声明(上):接口设计的 18 条军规18-21⭐⭐⭐15 min
第 5 篇设计与声明(下):pass-by-value 与非成员函数22-25⭐⭐⭐14 min
第 6 篇实现:变量定义、转型、inline 与编译依赖26-31⭐⭐⭐17 min
第 7 篇继承与 OOP(上):public 继承与名称遮掩32-36⭐⭐⭐⭐18 min
第 8 篇继承与 OOP(下):NVI、复合与多重继承37-40⭐⭐⭐⭐16 min
第 9 篇模板与泛型:traits、template 与元编程41-48⭐⭐⭐⭐20 min
第 10 篇定制 new/delete:内存池与 placement new49-52⭐⭐15 min
第 11 篇杂项 + 总结:编译器警告、TR1、Boost53-55⭐⭐12 min
合计11 篇文章55 条款-约 3.5 小时

四、每篇概览:核心要点速览

4.1 第 1 篇:让自己习惯 C++(条款 1-4)

核心论点:C++ 是个”多范式联邦”——C、Object-Oriented C++、Template C++、STL 四个子语言各有规矩。

关键条款

条款标题一句话精髓
01视 C++ 为一个语言联邦C++ = 4 个子语言,规则不同
02尽量以 const/enum/inline 替换 #define编译器替你抓错,比预处理器靠谱
03尽可能使用 constconst 是给编译器的”不变契约”
04确定对象被使用前已先被初始化永远在构造时初始化成员,避免”读取未初始化内存”

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 条款 02:避免 #define
#define ASPECT_RATIO 1.653 // ❌ 名字 ASPECT_RATIO 没进符号表,编译错时找不到

constexpr double AspectRatio = 1.653; // ✅ 进符号表,编译器认识

// 条款 03:const 的威力
class TextBlock {
public:
const char& operator[](size_t pos) const { return text_[pos]; } // const 版本
char& operator[](size_t pos) { return text_[pos]; } // non-const 版本
// 两个重载使 const TextBlock 只能读,TextBlock 可读可写
};

// 条款 04:成员初始化用 member initialization list
class PhoneNumber { /*...*/ };
class ABEntry {
std::string name_;
PhoneNumber phone_;
int age_;
public:
ABEntry(const std::string& name, const PhoneNumber& phone, int age)
: name_(name), phone_(phone), age_(age) // ✅ 一次构造
{}
// vs 在函数体里赋值:name_ = name; // 先 default 构造,再赋值 —— 两次操作
};

4.2 第 2 篇:构造/析构/赋值(条款 5-12)

核心论点:C++ 编译器会默默为你生成构造、拷贝、析构、赋值函数——不显式管理 = 隐性灾难。

关键条款

条款标题一句话精髓
05了解 C++ 默默编写并调用哪些函数编译器默认生成 default ctor、copy ctor、copy assignment、dtor
06若不想使用编译器自动生成的函数,就该明确拒绝= delete
07为多态基类声明 virtual 析构函数防止派生类对象只析构基类部分
08别让异常逃离析构函数析构抛出 = terminate
09绝不在构造和析构过程中调用 virtual 函数派生类还没初始化,调用就是 UB
10operator= 返回 *this 的引用链式赋值
11operator= 中处理”自我赋值”安全且异常安全
12复制对象时勿忘其每一个成分拷贝构造 / 拷贝赋值 要 copy 所有成员 + 基类部分

经典示例(Rule of Three)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class String {
char* data_;
size_t size_;
public:
String(const char* s) : size_(std::strlen(s)) {
data_ = new char[size_ + 1];
std::memcpy(data_, s, size_ + 1);
}

// 条款 11:copy-and-swap
String& operator=(String rhs) { // 传值 = 一次拷贝
swap(rhs);
return *this;
}

// 拷贝构造
String(const String& other) : size_(other.size_) {
data_ = new char[size_ + 1];
std::memcpy(data_, other.data_, size_ + 1);
}

void swap(String& other) noexcept {
std::swap(data_, other.data_);
std::swap(size_, other.size_);
}

~String() { delete[] data_; }
};

4.3 第 3 篇:资源管理(条款 13-17)

核心论点RAII(Resource Acquisition Is Initialization)是 C++ 资源管理的核心范式。把资源的获取放在构造函数、释放放在析构函数,让编译器保证”绝不泄漏”。

关键条款

条款标题一句话精髓
13以对象管理资源RAII 范式
14在资源管理类中小心 copying 行为禁止复制 / 引用计数 / 复制底层资源 / 转移所有权
15在资源管理类中提供对原始资源的访问get() 隐式转换函数
16成对使用 newdelete 时要采取相同形式new[]delete[]
17以独立语句将 newed 对象置入智能指针防止”new 成功、传参抛出”导致的泄漏

示例(条款 13)

1
2
3
4
5
6
7
8
9
10
11
12
13
// ❌ 危险:手动管理资源
void process() {
Investment* pInv = createInvestment(); // 假设可能抛出
...
delete pInv; // 抛出后永远不会执行 → 泄漏
}

// ✅ RAII:智能指针
void process() {
std::auto_ptr<Investment> pInv(createInvestment()); // C++11 后用 unique_ptr
...
// 函数退出时 pInv 析构,自动 delete
}

4.4 第 4、5 篇:设计与声明(条款 18-25)

核心论点好的接口 = 正确的语义 + 容易用对、难用错。这一部分教你怎么”设计契约”。

条款标题一句话精髓
18让接口容易被正确使用,不易被误用类型一致、限制值、加 const
19设计 class 犹如设计 type把 class 当”语言作者”来思考
20宁以 pass-by-reference-to-const 替换 pass-by-value避免无谓的拷贝、避免对象切割
21必须返回对象时,别妄想返回其 reference不要返回栈/堆局部变量的引用
22将成员变量声明为 private封装是”所有实现的细节”
23宁以 non-member、non-friend 替换 member 函数增加封装性、包裹弹性
24若所有参数皆需类型转换,请为此采用 non-member 函数跨类转换的灵活性
25考虑写一个不抛异常的 swap性能优化 + 接口正交

示例(条款 20)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ❌ pass-by-value:成本 + 对象切割
class Window { /*...*/ };
class WindowWithScrollBar : public Window { /*...*/ };

void printNameAndDisplay(Window w) { // 拷贝!而且只切到 Window 部分
std::cout << w.name();
w.display();
}

// ✅ pass-by-reference-to-const
void printNameAndDisplay(const Window& w) { // 0 拷贝,多态保留
std::cout << w.name();
w.display();
}

4.5 第 6 篇:实现(条款 26-31)

核心论点实现细节决定性能、可维护性、编译时间。

条款标题一句话精髓
26尽可能延后变量定义式的出现时间减少无谓的默认构造
27尽量少做转型动作C 风格 cast 不可逆;用 const_cast/dynamic_cast/static_cast/reinterpret_cast
28避免返回 handles 指向对象内部成分避免 handle 比对象”长寿”导致悬空
29为”异常安全”而努力是值得的basic / strong / nothrow 三级保证
30透彻了解 inlining 的里里外外inline 是编译期决定,对调试有影响
31将文件间的编译依存关系降至最低pimpl 模式,前置声明

示例(条款 31:pimpl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Person.h
#include <memory>
#include <string>
class PersonImpl; // 前置声明,隐藏实现
class Date;
class Address;

class Person {
public:
Person(const std::string& name, const Date& birthday, const Address& addr);
std::string name() const;
std::string birthDate() const;
std::string address() const;
// ... 大量接口
private:
std::shared_ptr<PersonImpl> pImpl_; // 编译防火墙
};

4.6 第 7、8 篇:继承与 OOP(条款 32-40)

核心论点OOP 设计的核心是”is-a”和”has-a”关系。这一部分教你怎么判断什么时候用继承、什么时候用复合。

条款标题一句话精髓
32确定你的 public 继承塑模出 is-a 关系企鹅 is-a 鸟,但不会飞
33避免遮掩继承而来的名称using Base::func 或转交函数
34区分接口继承和实现继承纯虚 / 非纯虚 / 非虚
35考虑 virtual 函数以外的其他选择NVI、function pointer、strategy、trampoline
36绝不重新定义继承而来的 non-virtual 函数违反 is-a
37绝不重新定义继承而来的缺省参数值缺省参数是静态绑定
38通过复合塑模出 has-a 或”根据某物实现出”composition
39明智而审慎地使用 private 继承实现继承,但 is-implemented-in-terms-of
40明智而审慎地使用多重继承菱形继承、virtual base

示例(条款 32)

1
2
3
4
5
6
7
8
9
class Bird { /*virtual*/ void fly(); /*...*/ };
class Penguin : public Bird { /*...*/ }; // ❌ 企鹅不会飞!

// ✅ 方案:拆开接口
class Bird { /*...*/ };
class FlyingBird : public Bird {
virtual void fly();
};
class Penguin : public Bird { /* 没有 fly */ };

4.7 第 9 篇:模板与泛型(条款 41-48)

核心论点模板是 C++ 编译期多态的核心,掌握它才能写出可复用的库。

条款标题一句话精髓
41了解隐式接口和编译期多态template 的接口是”表达式有效即可”
42了解 typename 的双重意义模板参数 vs 嵌套从属名称
43学习处理模板化基类内的名称this->using Base::func、显式特化
44将与参数无关的代码抽离 templates减少代码膨胀
45运用成员函数模板接受所有兼容类型智能指针的泛化拷贝构造
46需要类型转换时请为模板定义非成员函数operator* 等需要模板友元
47请使用 traits classes 表现类型信息iterator_traits<T>::iterator_category
48认识 template 元编程编译期计算(TMP)

示例(条款 47)

1
2
3
4
5
6
7
8
9
10
// 经典 traits:advance
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
if (typeid(std::iterator_traits<IterT>::iterator_category)
== typeid(std::random_access_iterator_tag)) {
iter += d; // O(1) for random access
} else {
while (d--) ++iter; // O(n) for others
}
}

4.8 第 10 篇:定制 new/delete(条款 49-52)

核心论点:99% 的项目不需要重载 new/delete——但剩下 1% 的极端场景(嵌入式、高频交易、内存池),这一章就是救命稻草。

条款标题一句话精髓
49了解 new-handler 的行为内存不足时的回调
50了解 new 和 delete 的合理替换时机统计、加速、降低默认开销
51编写 new 和 delete 时需固守常规处理 0 字节、对齐、最大 size
52写了 placement new 也要写 placement delete配对处理

4.9 第 11 篇:杂项 + 总结(条款 53-55)

核心论点:最后三条是”态度与方向”。

条款标题一句话精髓
53不要轻忽编译器的警告严肃对待每个 warning
54让自己熟悉包括 TR1 在内的标准程序库std::shared_ptr/std::function/std::bind
55让自己熟悉 Boost“准标准库”,C++ 委员会的”实验场”

五、4 条学习路径:按”角色”和”目的”选你的路线

graph TD
    START(["🎯 你想从这本书得到什么?"]) --> Q1{"当前水平?"}

    Q1 -->|"入门"| P1["📘 初读路径\n第 1 → 2 → 3 → 4 → 5 → 11"]
    Q1 -->|"进阶"| P2["📗 进阶路径\n第 1 → 2 → 3 → 6 → 7 → 8 → 9 → 11"]
    Q1 -->|"面试"| P3["📕 面试突击\n第 2 → 3 → 7 → 8 → 9 → 10"]
    Q1 -->|"性能优化"| P4["📙 性能路径\n第 3 → 6 → 9 → 10 → 11"]

    P1 --> DONE1(["✅ 建立 C++ 编程的'宪法'"])
    P2 --> DONE2(["✅ 写出工业级 C++"])
    P3 --> DONE3(["✅ 拿下 90% C++ 面试题"])
    P4 --> DONE4(["✅ 写出 0 浪费的 C++"])

    style START fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style Q1 fill:#FFF9C4,stroke:#F9A825,color:#333
    style P1 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style P2 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style P3 fill:#FFB3C6,stroke:#F48FB1,color:#333
    style P4 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style DONE1 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style DONE2 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style DONE3 fill:#FFB3C6,stroke:#F48FB1,color:#333
    style DONE4 fill:#FFDAB9,stroke:#FFAB76,color:#333

5.1 路径对比表

路径适用人群阅读篇数目标时长
初读路径入门 / 1~2 年6 篇建立基本功2 周
进阶路径3~5 年 / 工业级开发8 篇系统化 C++ 思维4 周
面试突击求职 / 跳槽6 篇高频考点全覆盖2 周
性能路径性能调优 / 嵌入式5 篇写出”硬件友好”的 C++2 周

5.2 推荐阅读顺序

阶段任务产出
第 1 周读第 1、2、3 篇掌握 C++ 思维 + RAII + 拷贝控制
第 2 周读第 4、5、6 篇掌握接口设计 + 实现细节
第 3 周读第 7、8 篇掌握 OOP 设计的核心矛盾
第 4 周读第 9、10、11 篇掌握模板 + 内存底层 + 工具链

六、《Effective C++》与本系列的关系

维度原书本系列
形式55 个独立条款11 篇主题化文章
语言中英文术语混用统一中文 + 关键英文标注
代码部分有全部补齐 C++17 完整可运行示例
图表大量 Mermaid 图、对比表、决策树
新特性对照每条配 C++11/14/17 演进注释
配套实验15+ 个可编译运行的 demo

七、章节依赖关系:哪些篇要按顺序读?

graph TB
    P1["第1篇\n基础哲学"] --> P2["第2篇\n构造析构"]
    P2 --> P3["第3篇\n资源管理"]
    P2 --> P4["第4-5篇\n设计"]
    P4 --> P6["第6篇\n实现"]
    P4 --> P7["第7-8篇\nOOP"]
    P4 --> P9["第9篇\n模板"]
    P3 --> P10["第10篇\nnew/delete"]
    P1 --> P11["第11篇\n杂项"]

    style P1 fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style P2 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style P3 fill:#FFF9C4,stroke:#F9A825,color:#333
    style P4 fill:#FFDAB9,stroke:#FFAB76,color:#333
    style P6 fill:#FFB3C6,stroke:#F48FB1,color:#333
    style P7 fill:#E8D5F5,stroke:#CE93D8,color:#333
    style P9 fill:#C7CEEA,stroke:#9FA8DA,color:#333
    style P10 fill:#B5EAD7,stroke:#80CBC4,color:#333
    style P11 fill:#F5F5F5,stroke:#9E9E9E,color:#333

建议

  • 第 1、2 篇必先读:奠定基础
  • 第 3 篇紧接其后:RAII 范式贯穿全书
  • 第 4~9 篇可并行:按”设计/实现/OOP/模板”分主题读
  • 第 10、11 篇可跳读:性能优化部分,初期可跳过

八、与其他经典 C++ 书的关系

关系
《C++ Primer》入门语法;本系列是它的”上层建筑”
《Effective Modern C++》2014 年的”续集”,讲 C++11/14;本系列是其”前身”
《More Effective C++》同系列姊妹篇;本系列是其”哲学扩展”
《深度探索 C++ 对象模型》编译器视角;本系列是”应用层视角”
《STL 源码剖析》模板库实现细节;本系列在条款 47/48 涉及
《设计模式》OOP 设计模式;本系列条款 35、38 涉及

九、配套资源:实验代码 + 工具链

9.1 编译环境

工具版本要求备注
g++≥ 9.0(C++17)主流 Linux 发行版自带
clang≥ 10.0更好的错误信息
CMake≥ 3.15项目构建
AddressSanitizer集成在 GCC/Clang内存检测

9.2 推荐实验清单

实验涉及条款难度
编译期 const 传播03
Rule of Three 实现5, 11, 12⭐⭐
智能指针循环引用13, 14⭐⭐
pass-by-value vs reference20
转型成本测试27⭐⭐
pimpl 模式31⭐⭐
模板特化与 traits45, 47⭐⭐⭐
内存池实现50, 51⭐⭐⭐

十、55 条条款索引速查表

条款主题标题所属篇目
01基础视 C++ 为一个语言联邦第 1 篇
02基础尽量以 const/enum/inline 替换 #define第 1 篇
03基础尽可能使用 const第 1 篇
04基础确定对象被使用前已先被初始化第 1 篇
05构造/析构了解 C++ 默默编写并调用哪些函数第 2 篇
06构造/析构若不想使用编译器自动生成的函数第 2 篇
07构造/析构为多态基类声明 virtual 析构函数第 2 篇
08构造/析构别让异常逃离析构函数第 2 篇
09构造/析构绝不在构造和析构过程中调用 virtual 函数第 2 篇
10构造/析构让 operator= 返回 *this 的引用第 2 篇
11构造/析构在 operator= 中处理”自我赋值”第 2 篇
12构造/析构复制对象时勿忘其每一个成分第 2 篇
13资源管理以对象管理资源第 3 篇
14资源管理在资源管理类中小心 copying 行为第 3 篇
15资源管理在资源管理类中提供对原始资源的访问第 3 篇
16资源管理成对使用 new 和 delete 时要采取相同形式第 3 篇
17资源管理以独立语句将 newed 对象置入智能指针第 3 篇
18设计让接口容易被正确使用,不易被误用第 4 篇
19设计设计 class 犹如设计 type第 4 篇
20设计宁以 pass-by-reference-to-const 替换 pass-by-value第 4 篇
21设计必须返回对象时,别妄想返回其 reference第 4 篇
22设计将成员变量声明为 private第 5 篇
23设计宁以 non-member、non-friend 替换 member 函数第 5 篇
24设计若所有参数皆需类型转换第 5 篇
25设计考虑写一个不抛异常的 swap第 5 篇
26实现尽可能延后变量定义式的出现时间第 6 篇
27实现尽量少做转型动作第 6 篇
28实现避免返回 handles 指向对象内部成分第 6 篇
29实现为”异常安全”而努力是值得的第 6 篇
30实现透彻了解 inlining 的里里外外第 6 篇
31实现将文件间的编译依存关系降至最低第 6 篇
32继承/OOP确定 public 继承塑模出 is-a 关系第 7 篇
33继承/OOP避免遮掩继承而来的名称第 7 篇
34继承/OOP区分接口继承和实现继承第 7 篇
35继承/OOP考虑 virtual 函数以外的其他选择第 7 篇
36继承/OOP绝不重新定义继承而来的 non-virtual 函数第 8 篇
37继承/OOP绝不重新定义继承而来的缺省参数值第 8 篇
38继承/OOP通过复合塑模出 has-a 或”根据某物实现出”第 8 篇
39继承/OOP明智而审慎地使用 private 继承第 8 篇
40继承/OOP明智而审慎地使用多重继承第 8 篇
41模板/泛型了解隐式接口和编译期多态第 9 篇
42模板/泛型了解 typename 的双重意义第 9 篇
43模板/泛型学习处理模板化基类内的名称第 9 篇
44模板/泛型将与参数无关的代码抽离 templates第 9 篇
45模板/泛型运用成员函数模板接受所有兼容类型第 9 篇
46模板/泛型需要类型转换时请为模板定义非成员函数第 9 篇
47模板/泛型请使用 traits classes 表现类型信息第 9 篇
48模板/泛型认识 template 元编程第 9 篇
49内存底层了解 new-handler 的行为第 10 篇
50内存底层了解 new 和 delete 的合理替换时机第 10 篇
51内存底层编写 new 和 delete 时需固守常规第 10 篇
52内存底层写了 placement new 也要写 placement delete第 10 篇
53杂项不要轻忽编译器的警告第 11 篇
54杂项让自己熟悉包括 TR1 在内的标准程序库第 11 篇
55杂项让自己熟悉 Boost第 11 篇

十一、读完本系列后能做什么?

11.1 立刻能做(10 分钟)

  • 翻一下你最近写的 C++ 代码,找出 #define 宏,能换成 constexpr 的就换
  • 给所有 const 的成员函数补上 const 关键字
  • 检查所有基类的析构函数是否 virtual

11.2 今天能做(1 小时)

  • 读完本总览,按 §5 选择你的阅读路径
  • 写一段 200 字的笔记:「我以前对 C++ 的误解是什么」

11.3 这一周能做

  • 选 5 个条款,写”过去的我 vs 现在的我”对比笔记
  • g++ -Wall -Wextra -Werror 重新编译你最近的项目
  • 找一个开源 C++ 项目(如 fmtspdlog),看它遵循了哪些条款

十二、行动召唤

Effective C++ 不会让你变成 C++ 大师,但它是”从能写”到”写得专业”的分水岭。

读完这 11 篇文章,你对 C++ 的理解会从”知道语法”升级到”懂得权衡”——这才是 5 年经验和 1 年经验的真正差距。

下一篇:第 1 篇《让自己习惯 C++:视 C++ 为语言联邦》——我们从”C++ 到底是个什么语言”开始。


系列标签#C++ #Effective C++ #Scott Meyers #编程规范 #C++98 #C++17 #C++11 #资源管理 #模板 #OOP

如果这篇总览对你有帮助,请点赞、在看、转发三连。也欢迎在评论区留下你最想看哪个条款的深入解读。