(C++ Coding Standards: 101 Rules, Guidelines, and Best Practices)
组织及策略上的问题(Organizational and Policy Issues)
- 0. 不拘小节(或:了解什么不需要被规范化)。 - 1. 在高警告级别下干净地编译。 - 2. 使用自动化的构建(build)系统 - 3. 使用版本控制系统(version control system)。 - 4. 在代码复查上投资。
设计风格(Design Style)
- 5. 给每一个实体分配一份内聚的职责。 - 6. 以正确,简单,清晰为上。 - 7. 了解何时及如何为可伸缩性编写代码。 - 8. 不要过早地优化。 - 9. 不要过早地退而求次。 - 10. 将全局和共享的数据减至最少。 - 11. 隐藏信息。 - 12. 了解何时及如何为并发性编写代码。 - 13. 确保资源为对象所占有。使用显式的RAII和智能指针。
编程风格(Coding Style)
- 14. 宁可在编译和链接时出错也不要在运行时出错。 - 15. 主动使用const。 - 16. 避免使用宏。 - 17. 避免使用魔数(magic numbers)。 - 18. 尽可能局部地声明变量。 - 19. 始终初始化变量。 - 20. 避免太长的函数。避免太深的嵌套。 - 21. 避免不同的编译单元在初始化过程中的依赖关系。 - 22. 将定义时的依赖性降至最低。避免循环依赖性。 - 23. 保证头文件的自足性(Make header files self-sufficient)。 - 24. 始终用内部#include防护哨。绝对不要用外部#include防护哨。
函数与操作符(Functions and Operators)
- 25. 通过值,(智能)指针,或引用适当地取得参数。 - 26. 在重载操作符时,要保留被重载操作符的自然语义。 - 27. 最好是保持算术和赋值运算符的标准形式。 - 28. 最好是保持标准形式的++和--。最好是调用前缀的形式。 - 29. 考虑通过重载来避免隐式的类型转换。 - 30. 避免重载&&, ||, 或, (逗号)。 - 31. 不要编写对函数参数的求值顺序有依赖性的代码。
类设计及继承(Class Design and Inheritance)
- 32. 清楚自己要编写什么类型的类。 - 33. 最好是设计最小型的类而不要设计巨型类。 - 34. 优先采用聚合,其次才是继承。 - 35. 避免继承自未设计为基类的类。 - 36. 最好是提供抽象接口。 - 37. 公有继承代表可替换性。继承,不是为了重用,而是为了被重用。 - 38. 安全地覆盖虚函数。 - 39. 考虑使虚函数成为非公有函数,使公有函数成为非虚函数。 - 40. 避免提供隐式转换。 - 41. 使类的数据成员为私有,除非是无行为的聚合类(C风格的结构)。 - 42. 不要泄露你的内部实现。 - 43. 明智地使用Pimpl惯用法。 - 44. 最好是编写非成员非友元函数。 - 45. 始终同时提供new和delete。 - 46. 如果你提供类特有的new,那么要提供所有的标准形式(plain,in-place,及nothrow)。
构造,析构,及复制操作(Construction, Destruction, and Copying)
- 47. 以相同的顺序定义及初始化成员变量。 - 48. 在构造函数中最好是用初始化列表而避免用赋值操作符。 - 49. 避免在构造函数和析构函数中调用虚函数。 - 50. 使基类的析构函数成为公有的虚函数,或受保护的非虚函数。 - 51. 析构函数,资源释放函数,以及swap绝不会失败。 - 52. 以一致的方式进行复制和销毁。 - 53. 显式地允许或禁止复制。 - 54. 避免分割对象。考虑用Clone来取代在基类中进行复制。 - 55. 最好是保持赋值操作符的标准形式。 - 56. 只要合理,就(正确地)提供不会失败的swap。
名字空间与模块(Namespaces and Modules)
- 57. 把类型和它的非成员函数接口放在同一个名字空间中。 - 58. 除非有意让类型和函数协作,否则把它们放在单独的名字空间中。 - 59. 不要在头文件中或#include语句之前写名字空间层级的using。 - 60. 避免在不同的模块中分配和释放内存。 - 61. 不要在头文件中定义具有链接属性的实体(entities with linkage)。 - 62. 不要让异常在传递时跨越模块的边界。 - 63. 在模块的接口中使用可移植的类型。
模板与泛型(Templates and Genericity)
- 64. 明智地结合静态多态性和动态多态性。 - 65. 有意地并显式地定制。 - 66. 不要特化函数模板。 - 67. 不要在无意中编写不通用的代码。
错误处理与异常(Error Handling and Exceptions)
- 68. 大量使用断言来说明内部的假设和不变性。 - 69. 设立一套合理的错误处理策略,并严格遵循。 - 70. 区分错误与非错误。 - 71. 设计并编写能够安全地处理错误的代码。 - 72. 尽量用异常来报告错误。 - 73. 抛出值,捕获引用。 - 74. 适当地报告,处理并转换错误。 - 75. 避免异常规格(exception specifications)。
STL容器(STL: Containers)
- 76. 默认情况下使用vector。否则选择其它合适的容器。 - 77. 用vector和string取代数组。 - 78. 使用vector(以及string::c_str)来和非C++ API交换数据。 - 79. 仅在容器中存储值和智能指针。 - 80. 与其它方法相比,要尽量使用push_back来扩大容器。 - 81. 与单元素操作相比,要尽量使用区间操作。 - 82. 使用公认的惯用法来真正地缩小容量以及真正地删除元素。
STL算法(STL: Algorithms)
- 83. 使用一个带检查的(checked)STL实现。 - 84. 与手工编写的循环相比,要尽量调用STL算法。 - 85. 使用正确的STL查找算法。 - 86. 使用正确的STL排序算法。 - 87. 使predicate成为纯函数(pure function)。 - 88. 在用作算法和比较器(comparer)时,要优先用函数对象来代替函数。 - 89. 正确地编写函数对象(Function Object)。
类型安全性(Type Safety)
- 90. 避免类型选择(type switching);尽量使用多态。 - 91. 依赖于对象类型,而不要依赖于对象的表示方法。 - 92. 避免使用reinterpret_cast。 - 93. 避免用static_cast来强制转换指针类型。 - 94. 避免强制去除const。 - 95. 不要用C风格的强制类型转换。 - 96. 不要对非POD类型使用memcpy或memcmp。 - 97. 不要用union来重新解释数据。 - 98. 不要使用varargs(省略号)。 - 99. 不要使用无效的对象。不要使用不安全的函数。 - 100. 不要以多态方式处理数组。