C++编程规范纲要要点小结
这是一本好书, 可以让你认清自己对C++的掌握程度. 看完之后,给自己打分,我对C++了解多少? 答案是不足20分. 对于我自己是理所当然的问题, 就不提了, 记一些有启发的条目和细节:
(*号表示不能完全理解,实力升级了之后回头看)
一般性问题:
1. 不要在注释中重复写代码语义,这样很容易产生不一致. 应该编写的是解释方法和原理的说明性注释.
2. 不要对每个项目每个文件进行强制的排版格式规定, 在同一个文件中风格一致即可.
3. 匈牙利记法是混用了类型不安全语言中的设施, 在面向对象语言中可以存在, 但是有害无益, 在泛型编程中则根本不可行, 在规范中禁用该记法则是合理的.
4. 用提倡更短小更简单的函数来代替规定函数单入口单出口.
5. “定义了从未使用的变量”这个警告可以通过无意义地使用它一下而消除.(如果有必要的话)
6. “遗漏了return语句”可以通过在函数尾部加上一个ASSERT(!”should never get here!”);return -1;来消除警告(!”string”的结果为false)
7. 使用自动构建系统(自动的,可靠的,单操作的)
8. 使用版本控制系统(推荐CVS, 5人日以上的项目都推荐使用CVS)
9. 在代码审查上投入.(准备一份check list)
a) 良性压力
b) 提高质量
c) 思想交流
d) 快速培养入门者
e) 形成团队精神
f) 增强整体实力,提升自信心,动力和职业荣誉感
设计风格(依赖性管理):
10. 一个实体应该只有一个紧凑的职责(变量,类,函数,名称空间,模块和库),随着实体变大,其职责范围也会扩大,但不应该发散.
11. 正确,简单和清晰第一: 正确优于速度. 简单优于复杂. 清晰优于机巧. 安全优于不安全.
要避免使用程序设计语言中的冷僻特性. 应该使用最简单的有效技术
12. 编程中应知道何时和如何考虑可伸缩性
a) 使用灵活的,动态分配的数组
b) 了解算法的实际复杂性
c) 优先使用线性算法或者尽可能快的算法
d) 尽可能避免劣于线性复杂性的算法
e) 永远不要使用指数复杂性的算法
13. 不要进行不成熟的优化: 首先要保持代码的清晰可读, 易维护, 易重构.
14. 不要进行不成熟的劣化: 放松自己, 轻松编程. 不要悲观对自己没有信心.
a) 可以使用引用传递却用了值传递
b) 使用++前缀很适合却用了后缀
c) 在构造函数中赋值而不是使用初始化列表
d) 使用抽象和库.
15. 尽量减少全局和共享数据: 避免共享数据,尤其是全局数据. 共享数据会增加耦合度, 从而降低可维护性, 通常还降低性能. 为”无共享”而奋斗吧, 用通信方式(比如消息队列)来代替数据共享.
16. 隐藏信息: 不要公开提供抽象的实体的内部信息. 绝对不要将类的数据成员设为Public
17. 懂得何时和如何进行并发性编程.(这部分涉及的不多, 没有多少体会, 回头补看) 如果应用程序使用了多个线程或者进程, 应该知道如何尽量减少共享对象, 以及如何安全地共享必须共享的对象. 最重要的是避免死锁, 活锁和恶性的竞争条件.
18. 确保资源为对象所拥有. 使用显式的RAII(资源获取即初始化)和智能指针.
19. 不要在同一条语句内分配一个以上资源.
20. 宁可编译时和连接时错误, 也不要运行时错误(这条的论述不理解, 没概念, 回头重看.)
21. *积极使用const
22. 避免使用宏: 在C++中可以用const或者enum定义易于理解的常量,用inline避免函数调用的开销, 用template指定函数系列和类型系列, 用namespace避免名称冲突.(略去一大堆攻击宏的叙述.) 但#include #ifdef和assert仍不可避免.
23. 避免使用”魔数”: 用符号名称和表达式替换他们. 应该用符号常量代替直接写死的字符串,将字符串与代码分开(所有字符串放在一个CPP文件中), 这样非程序员也可以对其进行检查和更新.
24. 重要的特定于领域的常量可以放在名字空间一级.
25. 特定于类的常量, 可以在类定义中定义静态整数常量.(在.h中声明常量,在.cpp中定义值)
26. 尽可能局部地声明变量. 因为不能合理的初始化变量是c和c++错误的普遍来源. 但因为常量并不添加状态, 所以本条对常量并不适用.
27. 总是初始化变量 :未初始化的变量是C和C++中错误的常见来源。养成在使用内存之前先清除的习惯,可以避免这种错误,在变量定义的时候就初始化。
28. 使用默认初始值或者?:减少数据流和控制流的混合。
29. 用函数替代复杂的计算流。
30. 初始化数组,正确的初始化并不见得真的要对所有的数据进行操作。 比如:char path[MAX_PATH] = [‘/0’] 创建一个以零填充的空路径(c风格字符串)。
31. 避免函数过长,避免嵌套过深
a) 尽量紧凑,对一个函数只赋予一种职责
b) 不要自我重复
c) 优先使用&&(相对于if嵌套)
d) 不要过分使用try
e) 优先使用标准算法
f) 不要根据类型标签(type tag)进行分支(switch),优先使用多态函数
32. 避免跨编译单元的初始化依赖
33. 尽量减少定义性依赖。避免循环依赖。
a) 依赖倒置原理:不要让高层模块依赖于低层模块。应该让两者都依赖于抽象。
34. *头文件应该自给自足
35. 总是编写内部#include保护符,绝不要编写外部#include保护符。(好不容易才理解,累死了,就是说在头文件本身写保护符,而不是在包含的时候再用保护符。这样可以避免保护符名称不一致。在包含的时候就用不着保护符了。)
36. 正确的选择通过值、(智能)指针或者引用传递参数:分清输入参数、输出参数和输入/输出参数,分清值参数和引用参数。正确的传递参数。
37. 对于只做输入的参数:
a) 始终用const限制所有指向只输入参数的指针和引用。
b) 优先通过值来取得原始类型和复制开销比较低的值的对象。
c) 优先按const的引用取得其他用户定义类型的输入。
d) 如果函数需要其参数的副本,则可以考虑通过值传递代替通过引用传递。这在概念上等同于通过const引用传递加上一次复制,能够帮助编译器更好的优化掉临时变量。
38. 对于输出参数或者输入/输出参数:
a) 如果参数是可选的,或者函数需要保存这个指针的副本或者操控参数的所有权,那么优先通过(智能)指针传递。
b) 如果参数是必须的,而且函数无需保存指向参数的指针,或者无需操控其所有权,那么应该优先通过引用传递。这表明参数是必须的,而且调用者必须提供有效对象。
39. 保持重载操作符的自然语义
40. *优先使用运算操作符和复制操作符的标准形式。
41. 优先使用++和--的标准形式。优先调用前缀形式,因为其少创建了一个对象。这是成熟的优化。
42. 考虑重载以避免隐含类型转换。(不必要经历创建临时变量的麻烦)
43. 避免重载&&、||或,(逗号)(危害一大堆)
a) 内置的&&||符号是短路操作符,遇到false,&&会停止计算,遇到true,||会停止计算。
44. 不要编写依赖于函数参数求值顺序的代码:函数参数的求值顺序是不确定的。
45. *弄清所要编写的是那种类,然后根据具体情况编写。 分为:值类 基类 traits 策略类 异常类。
46. 用小类代替巨类。
47. 用组合代替继承:继承仅次于友元,是C++中第二紧密的耦合关系。紧密的耦合是一种不良现象,应该尽量避免。(后面还有好处一大堆,但是没提模式。)
48. 避免从并非要设计成基类的类中继承:要添加行为,应该添加非成员函数而不是成员函数,要添加状态,应该使用组合而不是继承。要避免从具体的基类继承。
49. 优先提供抽象接口:抽象接口有助于我们集中精力保证抽象的正确性,不至于受到实现或者状态管理细节的干扰。优先采用实现了(建模抽象概念的)抽象接口的设计层次结构。DIP(Dependency Inversioin Principle 依赖倒置原理)有三个基本的设计优点:更强壮,更灵活,更好的模块性。
50. 公用继承即可替换性。继承不是为了重用,而是为了被重用。
51. 使用继承的时候,不说“是一个”,而说“其行为像一个”,这样可以避免描述易于误解。
52. *实施安全的改写。
53. *考虑将虚拟函数声明为非公用的,将公用函数声明为非虚拟的。
54. *要避免提供隐式转换
55. *将数据成员设为私有的, 无行为的聚集(C语言形式的struct)
56. *不要公开内部数据
57. *明智地使用Pimpl
58. *优先编写非成员非友元函数
59. *总是一起提供new和delete(这里指重载它们之一时)
60. *如果提供类专门的new, 应该提供所有标准形式. (普通,就地和不抛出)
61. 以同样的顺序定义和初始化成员变量
62. 在构造函数中用初始化代替赋值.
63. 避免在构造函数和析构函数中调用虚拟函数(*可以使用”后构造函数”来实现类似目的)
64. *将基类析构函数设为公用且虚拟的, 或者保护且非虚拟的.
65. *析构函数,释放和交换绝对不能失败.
66. 一致地进行赋值和销毁.如果定义了赋值构造函数, 复制赋值操作符或者析构函数中的任何一个, 那么可能也需要定义另一个或另外两个.
67. 显式地启用或者禁止复制.
a) 如果赋值对你的类型没有意义, 那就通过将它们声明为私有的未实现函数来禁止复制构造和复制赋值.
b) 如果复制和复制赋值适合于T对象,但是正确的复制行为又不同于编译器生成的版本, 那么就自己编写函数并将他们设为私有的.
c) 使用编译器生成的版本,最好是加上一个明确的注释.
68. *避免切片. 在基类中考虑用克隆代替复制.
69. *使用标准的赋值形式. 在实现operator=时, 应该使用标准形式—具有特定签名的非虚拟形式.
70. *只要可行,就提供不会失败的swap (而且要正确的提供)
71. 将类型及其非成员函数接口置于同一名字空间中.
72. *应该将类型和函数分别置于不同的名字空间中,除非有意想让它们一起工作.
73. 不要在头文件中或者#include之前编写名字空间using
74. 要避免在不同的模块中分配和释放内存
75. *不要在头文件中定义具有链接的实体
76. *不要允许异常跨越模块边界传播.
77. *在模块的接口中使用具有良好可移植性的类型
78. *理智的结合静态多态性和动态多态性
79. 多态性的优势在于,同一段代码能够操作不同类型,甚至可以是在编写代码时不知道的类型.
80. *有意的进行显式自定义
81. *不要特化模板函数
82. 不要无意地编写不通用的代码
a) 使用!=代替<对迭代器进行比较
b) 使用迭代替代索引访问
c) 使用empty()代替size()==0
d) 使用层次结构中最高层的类提供需要的功能
e) 编写常量正确的代码
83. 广泛的使用断言记录内部假设和不变式
84. 千万不要在assert语句中编写具有副作用的表达式
85. 建立合理的错误处理策略, 并严格遵守. 包括
a) 鉴别: 哪些情况属于错误
b) 严重程度: 每个错误的严重或者紧急性
c) 检查: 哪些代码负责检查错误
d) 传递: 用什么机制在模块中报告和传递错误通知
e) 处理: 哪些代码负责处理错误
f) 报告: 怎样将错误记入日志, 或通知用户.
86. *区别错误与非错误
87. *设计和编写错误安全代码
88. *优先使用异常报告错误
89. 通过值抛出, 通过引用捕获
90. *正确地报告, 处理和转换错误
91. *避免使用异常规范
92. 默认时使用vector. 否则, 选择其他适合的容器
a) 编程时正确,简单和清晰是第一位的
b) 编程时只在必要时才考虑效率
c) 尽可能编写事务性的. 强错误安全的代码
93. vector具有如下性质:
a) 保证所有容器中最低的空间开销
b) 保证具有所有容器中对所存放元素进行存取的速度最快
c) 保证与生俱来的引用局部性,也就是说容器中相邻对象保证在内存中也相邻,这是其它标准容器无法保证的
d) 保证具有C语言兼容的内存布局,这与其它标准容器也不同
e) 保证具有所有容器中最灵活的迭代器(随机访问迭代器)
f) 几乎肯定具有最快的迭代器(指针,或性能向但与类,在非调试模式下迭代 器类经常可以被编译成与指针具有相同的速度),比其他所有容器的迭代器都快.
94. 用vector和string代替数组
a) 它们能够自动管理内存
b) 它们具有丰富的接口
c) 它们与C内存模型兼容
d) 它们能够提供更大范围的检查
e) 它们支持上述特性并未牺牲太多效率
f) 它们有助于优化
95. *使用vector(和string::c_str)与非C++API交换数据
96. *在容器中只存储值和智能指针
97. *用push_back代替其它扩展序列的方式
98. 多用范围操作, 少用单元素操作
99. *使用公认的惯用法真正的压缩容量,真正地删除元素
100. 算法即循环—只是更好. 算法是循环的”模式”, 在只用for语句实现的原始循环上增加了很多语义内容和其他丰富内容.
101. *使用带检查的STL实现
102. *用算法调用代替手工编写的循环
a) 提高交流层次
b) 正确性, 效率较好.
103. *使用正确的STL排序算法
a) Partition, stable_partition和nth_element算法是线性时间的.
b) Partial_sort, sort, stable_sort和nth_element需要随机访问迭代器.
104. *使谓词成为纯函数
a) 谓词就是返回是或否的函数对象. 从数学意义上来说, 如果函数的结果只取决于其参数,则该函数就是一个纯函数.
105. *算法和比较器的参数应多用函数对象少用函数
106. *正确编写函数对象
107. 避免使用类型分支,多使用多态
108. *依赖类型, 而非其表示方式
a) 不要对对象在内存中的准确表示方式做任何假设. 相反应该让类型决定如何在内存中读写其对象.
109. 避免使用reinterpret_cast
110. 避免对指针使用static_cast
a) 用dynamic_cast, 重构, 甚至重新设计来代替它.
111. 避免强制转换const
112. *不要使用c风格的强制转换
113. 不要对非POD进行memcpy或者memcmp操作
114. *不要使用联合重新解释表示方式
115. 不要使用可变长参数(…)
116. 不要使用失效对象. 不要使用不安全函数
a) 已销毁对象
b) 语义失效对象
c) 从来都有效的对象
117. *不要多态地处理数组
C++编程规范纲要要点小结的更多相关文章
- Python 编程规范-----转载
Python编程规范及性能优化 Ptyhon编程规范 编码 所有的 Python 脚本文件都应在文件头标上 # -*- coding:utf-8 -*- .设置编辑器,默认保存为 utf-8 格式. ...
- 华为C语言编程规范
DKBA华为技术有限公司内部技术规范DKBA 2826-2011.5C语言编程规范2011年5月9日发布 2011年5月9日实施华为技术有限公司Huawei Technologies Co., Ltd ...
- 中兴软件编程规范C/C++
Q/ZX 深圳市中兴通讯股份有限公司企业标准 (设计技术标准) Q/ZX 04.302.1–2003 软件编程规范C/C++ 20 ...
- Python 浅谈编程规范和软件开发目录规范的重要性
最近参加了一个比赛,然后看到队友编程的代码,我觉得真的是觉得注释和命名规范的重要性了,因为几乎每个字符都要咨询他,用老师的话来说,这就是命名不规范的后续反应.所以此时的我意识到写一篇关于注释程序的重要 ...
- helloworld讲解cocos2d-x的编程思路与要点
用helloworld讲解cocos2d-x的编程思路与要点 本文以cocos2d-x的helloworld为例,讲解cocos2d-x引擎的特点和要点,2.2为了展示新功能,把包括屏幕自适应在内的新 ...
- Java结对编程四则运算一周小结
Java结对编程四则运算一周小结 需求分析 对于四则运算来说最主要的就是要计算出产生的式子(字符串的形式). 设计思路 总体可将这个项目分解为几个部分:产生式子,计算式子,判断对错并记录: 具体的思路 ...
- 单片机C基本编程规范
为了提高源程序的质量和可维护性,从而最终提高软件产品生产力,特编写此规范.本标准规定了程序设计人员进行程序设计时必须遵循的规范.本规范主要针对单片机编程语言和08编译器而言,包括排版.注释.命名.变量 ...
- C++语言编程规范
前言 这里参考了<高质量C++C 编程指南 林锐>.<google C++编程指南>以及<华为C++语言编程规范>编写了这份C++语言编程规范文档,以合理使用 C+ ...
- python浅谈编程规范和软件开发目录规范的重要性
前言 我们这些初学者,目前要做的就是遵守代码规范,这是最基本的,而且每个团队的规范可能还不一样,以后工作了,尽可能和团队保持一致,目前初学者就按照官方的要求即可 新人进入一个企业,不会接触到核心的架构 ...
随机推荐
- C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介
C#中IPAddress类/Dns类/IPHostEntry类/IPEndPoint用法简介 IP是一种普遍应用于因特网.允许不同主机能够相互找到对方的寻址协议.IP地址由4个十进制的数字号码所组成, ...
- AC日记——圆桌聚餐 cogs 729
729. [网络流24题] 圆桌聚餐 ★★ 输入文件:roundtable.in 输出文件:roundtable.out 评测插件时间限制:1 s 内存限制:128 MB «问题描述: ...
- 牛客网 Wannafly挑战赛11 B.白兔的式子-组合数阶乘逆元快速幂
链接:https://www.nowcoder.com/acm/contest/73/B来源:牛客网 B.白兔的式子 时间限制:C/C++ 1秒,其他语言2秒空间限制:C/C++ 262144K, ...
- BZOJ——1622: [Usaco2008 Open]Word Power 名字的能量
http://www.lydsy.com/JudgeOnline/problem.php?id=1622 Description 约翰想要计算他那N(1≤N≤1000)只奶牛的名字的能量.每只 ...
- android-samples-mvp
Model–view–presenter (MVP)介绍 mvp在wiki上的介绍为 Model 定义用户界面所需要被显示的数据模型,一个模型包含着相关的业务逻辑 View View不应该处理业务 ...
- CDOJ_24 八球胜负
8球是一种台球竞赛的规则.台面上有7个红球.7个黄球以及一个黑球,当然还有一个白球.对于本题,我们使用如下的简化规则:红.黄两名选手轮 流用白球击打各自颜色的球,如果将该颜色的7个球全部打进,则这名选 ...
- AtCoder - 2581 Meaningful Mean
Problem Statement You are given an integer sequence of length N, a= {a1,a2,…,aN}, and an integer K. ...
- Hdoj 3506 Monkey Party
Discription Far away from our world, there is a banana forest. And many lovely monkeys live there. O ...
- C#中异常处理和Java的区别
捕获异常,同样是try...catch...,这个完全一样: 抛出异常,同样是throw,这个完全一样: 函数抛出怎样的异常,Java中可以用throws定义,而C#中不用定义,相当于throws E ...
- MySQL 查询某个列中同样值的数量统计
数据如今是这种,我想确定出type列中的news和image....甚至以后有其它值,他们分别有多少个. SELECT type, count(1) AS counts FROM material G ...