《Effective C++》规则速览
Scott Meyers 的《Effective C++(第三版)》副标题是“改善程序与设计的 55 个具体做法”,下面按原书顺序列出全部 55 条。
一、让自己习惯 C++
- 把 C++ 看作由 C、面向对象 C++、模板 C++ 和 STL 组成的语言联邦。
- 尽量用
const、enum和inline替代#define。 - 尽可能使用
const。 - 确保对象在使用前已经初始化。
二、构造、析构与赋值
- 了解编译器会自动生成和调用哪些特殊成员函数。
- 明确禁止使用不需要的编译器生成函数;现代 C++ 使用
= delete。 - 多态基类应声明虚析构函数。
- 不要让异常逃出析构函数。 // FIXME
- 不要在构造函数或析构函数中调用虚函数。
- 赋值运算符应返回
*this的引用。 // FIXME - 在
operator=中正确处理自赋值。 - 复制对象时不要遗漏任何成员或基类部分。
三、资源管理
- 使用对象管理资源,即采用 RAII。
- 仔细设计资源管理类的复制行为。
- 资源管理类应在必要时提供对原始资源的访问。
new和delete的形式必须匹配,数组应使用new[]和delete[]。- 将
new出来的对象立即放入智能指针,并使用独立语句完成。
四、设计与声明
- 让接口容易被正确使用,而且不容易被误用。
- 把类的设计当作类型的设计。
- 传递对象时优先使用
const引用,而不是按值传递。 - 必须返回新对象时,不要试图返回引用。
- 将数据成员声明为
private。 - 能用非成员、非友元函数实现时,优先于成员函数。
- 若所有参数都需要隐式类型转换,应将相关函数声明为非成员函数。
- 考虑提供不抛异常的
swap。 // FIXME
五、实现
- 尽可能推迟变量定义,直到真正需要它时。
- 尽量少做类型转换。
- 避免返回指向对象内部数据的句柄,如引用、指针或迭代器。
- 努力编写异常安全的代码。
- 理解
inline的适用场景和代价。 - 尽量减少文件之间的编译依赖。
六、继承与面向对象设计
- 公有继承必须表达 “is-a” 关系。 // FIXME
- 避免遮蔽继承而来的名称。
- 区分接口继承与实现继承。
- 考虑虚函数以外的设计方案。
- 不要重新定义继承而来的非虚函数。
- 不要重新定义继承而来的函数默认参数值。
- 用组合表达 “has-a” 或 “根据某物实现” 的关系。// FIXME
- 谨慎使用私有继承。 // FIXME
- 谨慎使用多重继承。
七、模板与泛型编程
- 理解隐式接口和编译期多态。
- 理解
typename的两种含义。 - 了解如何访问模板化基类中的名称。
- 将与模板参数无关的代码移出模板,避免代码膨胀。
- 使用成员函数模板接受所有兼容类型。
- 需要隐式类型转换时,在类模板内部定义非成员函数。
- 使用 traits 类表达和查询类型信息。
- 了解模板元编程。
八、定制 new 与 delete
- 理解
new-handler的行为。 - 理解何时值得替换
new和delete。 - 编写自定义
new和delete时遵循惯例。 - 编写 placement
new时,也要编写对应的 placementdelete。
九、其他
- 重视编译器警告。
- 熟悉标准库;书中提到的 TR1 已被后续 C++ 标准大体吸收。
- 熟悉 Boost,但现代 C++ 中应先检查标准库是否已有对应设施。
阅读备注
- 第 17 条的例子比较极端:对于这种由异常触发的资源泄漏,有没有系统性的防范方案?
- 本书出版于 C++11 之前,
auto_ptr、TR1 等内容已经过时;阅读时应对应到unique_ptr、shared_ptr和现代标准库。
- template P16
- inline P16
-
static 在 C 语言的中间的作用 和 C++ 中间的作用的如何统一的 ?
- 为了的免除 “跨编译单元之初始化的的次序问题” 使用local 对象代替的 non-local 对象
本站所有文章转发 CSDN 将按侵权追究法律责任,其它情况随意。