Effective C++ 第三版学习地图
对齐第三版九章与 55 个 Items:从语言联邦和对象语义,经 RAII、接口、实现、继承与模板,走到 new/delete、warnings、标准库和 Boost。
学习目标
- 能说出第三版九章、55 个 Items 的范围、核心问题和前后依赖,不再使用旧四板块压缩目录
- 能设计对象语义、ownership、接口、实现、多态、generic 与 allocation 递进的个人学习路径
- 能使用预测、最小复现、正反测试和真实代码迁移证据验收每个 Item
从“55 条不是零散技巧”开始
Effective C++ 第三版把 55 个具体建议组织为九章。它们共同回答一个问题:怎样让 C++ 程序的正确性由对象生命周期、类型系统和明确 contract 承担,而不是依赖开发者每次都足够谨慎。
↡以第三版九章和 55 个官方 Items 为唯一顺序来源的学习结构。旧学习地图把全书压成四块,会让实现细节、new/delete 与杂项失去准确位置。当前路线逐 Item 保留原书边界。
↡一条只解决一个核心设计问题,并给出可验证行为准则的原书单元。第一章 Items 1-4:适应 C++
先理解 C++ 是 C、Object-Oriented C++、Template C++ 与 STL 组成的
↡不同子语言拥有不同抽象、传参和性能准则的复合语言模型。。
Items 2-4 用 const、enum、inline 和完整初始化替代脆弱预处理/未初始化状态。
class Session {
public:
explicit Session(Id id) : id_(id), active_(false) {}
private:
const Id id_;
bool active_;
};验收点:宏是否泄漏作用域;const 是否贯穿接口;成员、base、static objects 是否在首次使用前确定初始化。
第二章 Items 5-12:构造、析构与赋值
compiler 会生成 default/copy/destructor/assignment,但生成不等于语义正确。需要明确禁止 copy、让 polymorphic base destructor virtual、避免 destructor 抛异常、理解 constructor/destructor 期间 virtual dispatch,并让 assignment 返回 *this、处理 self-assignment、复制所有 members/bases。
class UniqueHandle {
public:
UniqueHandle(const UniqueHandle&) = delete;
UniqueHandle& operator=(const UniqueHandle&) = delete;
};第三章 Items 13-17:资源管理
资源取得后立即交给对象,destructor 覆盖 normal return、early return 和 exception。unique/shared/weak ownership 必须与业务生命周期一致;new/delete family 配对;独立语句建立 smart pointer,避免求值顺序中的泄漏窗口。
↡资源获取与管理对象初始化绑定,作用域结束自动执行配对释放。 ↡谁延长资源生命、谁负责最终释放、谁只是短期观察的明确协议。auto file = std::unique_ptr<FILE, FileCloser>(
std::fopen(path.c_str(), "rb"));
if (!file) throw FileError{};第四章 Items 18-25:设计与声明
接口应让正确使用自然、错误使用困难;class 设计就是 type 设计;默认 pass-by-reference-to-const;不返回 local/temporary handle;data private;能用 non-member non-friend 就减小访问面;对称转换放 non-member;为 user type 提供 non-throwing swap。
↡通过类型、构造和函数边界让非法状态或调用无法表达的接口。 ↡只有最少必要代码能访问 representation,从而减少不变量破坏面。第五章 Items 26-31:实现
延迟变量定义到真正需要且能初始化的位置;减少 casts;不要泄漏 internal handles;异常安全用 RAII、copy-and-swap 或 transaction;审慎 inline;通过 Pimpl、interface 和依赖反转降低 compilation dependency。
↡操作失败后保证不泄漏,并按 basic/strong/no-throw 层级约束状态。 ↡header 变化造成的 recompilation fan-out 和 binary coupling。第六章 Items 32-40:继承与面向对象设计
public inheritance 必须满足 is-a 与 substitutability。区分 interface inheritance 和 implementation inheritance;virtual alternatives 包括 NVI、strategy 与 function wrapper;不要重定义 inherited nonvirtual 或 default parameter;composition 表达 has-a/implemented-in-terms-of;private/multiple inheritance 只有语义和成本证据充分才用。
↡derived 可在所有 base client 中替换 base,并保持其行为 contract。 ↡public nonvirtual wrapper 统一检查和流程,private virtual hook 提供变化点。第七章 Items 41-48:模板与泛型编程
templates 的 implicit interface 由 valid expressions 构成,compile-time polymorphism 在实例化/重载阶段发生。掌握 typename、dependent base lookup、parameter-independent factoring、member templates、hidden friends、traits/tag dispatch 与 TMP。
↡由泛型代码必须成立的完整 expressions 组成、无需共同 base 的契约。 ↡通过 traits 抽取类型事实,再用 tags/overloads 在编译期选择实现。先预测 template error 位于 deduction、lookup、substitution 还是 conversion,再读诊断,不把“模板报错很长”当成无法定位。
第八章 Items 49-52:定制 new 和 delete
理解 new-handler 失败循环;只在 usage errors、statistics、performance、clustering 或 alignment 有证据时替换;自定义函数遵守 zero request、handler、alignment、derived size 和 null delete;placement new 必须有 matching placement delete 处理 constructor failure。
↡allocation 失败后调用当前处理器并重试,直至成功、抛异常或终止的控制流。 ↡placement allocation 与构造失败释放函数按额外参数类型对应。第九章 Items 53-55:杂项
warnings 是潜在语义/portability 信号;标准库提供 ownership、containers、algorithms 和 vocabulary;TR1/Boost 展示库设施从 peer review 到 standardization 的演进。
↡不同 compilers 与 libraries 共同构建,覆盖诊断和标准扩展差异。 ↡通过社区同行评审和多平台实践磨炼库设计,再为标准化提供证据。两条推荐路线
系统学习路线:1-12 对象语义 → 13-17 ownership → 18-31 接口/实现 → 32-40 多态 → 41-48 generic → 49-55 底层与工程。
问题驱动路线:泄漏先读 13-17/29;继承 bug 读 32-40;模板诊断读 41-48;allocator bug 读 49-52。问题解决后回到系统路线补前置。
↡以原书依赖顺序逐章建立完整模型的学习方式。 ↡从当前故障进入相关 Items,再回补其前置 contract 的学习方式。每个 Item 的验收方法
至少保留三类 evidence:错误代码确实复现;语言机制修复后行为改变;负例被 compiler/test 拒绝。仅能复述条款不算掌握。
↡证明问题、修复和迁移能力的代码、诊断、测试与审查记录。小结
- 第三版按九章组织 55 Items,不能压缩成丢失边界的四块目录
- 学习依赖从对象语义、ownership、接口、实现、多态走向 generic 与 allocation
- 每条 Item 用预测、最小复现、语言机制修复、正反测试和真实迁移验收
- 系统路线建立完整模型,问题路线解决故障后必须回补前置
名词解释
本章出现的专业名词,用大白话再讲一遍。
- 第三版九章路线
九章 55 Items 的官方学习结构。
- Item 学习单元
- 单一核心问题及可验证准则。
- 语言联邦
- C++ 多子语言及不同准则模型。
- 完整初始化
constructor body 前建立成员有效值。
- 编译器生成函数
- 隐式声明/定义的特殊成员。
- 完整复制语义
复制所有 base/member 并保持 contract。
- RAII
- 资源获取绑定 owner 初始化。
- ownership contract
拥有、释放和观察的生命周期协议。
- 易正确接口
- 让非法状态和调用难以表达。
- 封装访问面
能访问 representation 的最小代码集合。
- 异常安全保证
- 失败后资源和状态的层级承诺。
- 编译依赖
- header 变化造成的重编译和耦合。
- is-a substitutability
derived 保持 base 合约的替换性。
- NVI
- nonvirtual wrapper 加 virtual hook。
- 隐式接口
- template 所需有效表达式集合。
- traits 分派
- 类型信息抽取与静态实现选择。
- new-handler 循环
- 分配失败处理与重试流程。
- placement 配对
额外参数匹配的失败释放路径。
- 可移植性矩阵
- 多工具链和库的构建组合。
- 库标准化路径
- 评审实践到标准设施的演进。
- 系统学习路线
- 按依赖顺序建立完整模型。
- 问题驱动路线
- 故障切入后回补前置的方式。
- 条款证据链
- 复现、修复、测试和迁移证据。
练习
- 问题 1:为有裸资源和继承 bug 的旧模块选路线。 说明先后 Items 和 evidence。
- 问题 2:判断是否掌握 Item 37。 学习者能背“不要重定义默认参数”。
- 问题 3:制定四周学习计划。 每周必须有跨章节产出。