《高质量 C++/C 编程指南》笔记
林锐博士著,v1.0,2001-07-24 定稿。原为航天信息股份有限公司科研计划项目产物,是国内早期影响极大的 C/C++ 编码规范文档,也是微软 Asia 技术中心等机构的参考规范。全书 101 页,含课程设计与参考答案(附录 A/B 为笔试/上机样题)。
全书结构
- 第 1-6 章:编程风格(难度不高、细节多)——文件结构、程序版式、命名规则、表达式和基本语句、常量、函数设计
- 第 7-11 章:专题论述(技术难度高)——内存管理、C++ 函数高级特性、类的构造函数/析构函数/赋值函数、类的继承与组合、其它编程经验
核心观点
1. 代码风格是专业性的体现
- “程序是写给人读的,只是偶尔让计算机执行一下”
- 版式规则:空行划分逻辑块、代码行缩进 4 空格、指针
*属于变量(char *p;而非char* p;,避免char* a, b;的误解)、长行在低优先级操作符处拆分且续行对齐 - 命名:数组名用复数(
student_array),函数名用动宾词组(GetStudentName),禁止含义不清的命名如Flag、Data1 - 注释规则:注释与代码”同步”才有效,半个错误注释比没有更糟;
/*流式注释*/风格优于//(C++ 程序员用 // 会被误认为 C++ 新手写 C)
2. 表达式与基本语句的经典陷阱
if (x = 0)赋值误用:比较时应写成if (0 == x)(Yoda 条件)if ((min < A) && (A < max))写法错误——C/C++ 中min < A < max恒为真switch每个case必须以break结束do { ... } while(condition);分号不能漏- 减少循环体内语句量:把不变量提到循环外(如
for (i = n*(j+k); ...))
3. 函数设计契约
- 参数校验在函数入口用
assert;断言只在调试阶段生效,Release 版自动失效,不能再断言中写执行语句 - 指针释放后立即置
NULL,防止”野指针” - 函数功能内聚:一个函数只干一件事
- 返回值为指针或引用时,检查是否返回了”栈内存地址”或”已经free的堆内存”(悬垂指针)
- 避免函数参数过多;输入参数加
const保护
4. 内存管理(全书精华章)
- 三种内存分配:静态存储区(全局/static)、栈(自动释放、容量有限、效率极高)、堆(malloc/new,灵活但问题最多)
- 常见内存错误及对策:
- 分配未使用即引用 → 入口
assert(p!=NULL)或if(p==NULL)防错 - 未初始化就引用 → 内存缺省初值没有统一标准,宁可信其无;数组永远显式赋初值
- 越界 → for 循环次数”多 1 / 少 1”是惯犯
- 内存泄漏 → 申请与释放配对;“不是每次必现的泄漏最可怕”
- 释放后仍引用(free 后不置 NULL 的野指针)
- 分配未使用即引用 → 入口
malloc(0)与new失败返回:malloc(0)返回非 NULL 的”最小内存块”指针,operator new失败抛异常——new应写new(nothrow)才返回 NULL,所以if(p==NULL)式的 new 防错默认不成立- 二维动态数组的四种正确写法(含一级指针数组、二级指针、一维连续)
- 引用与指针的区别:引用一旦初始化不可更改、无空引用(但仍会有”空引用”,即
&(*NULL)这种引用空指针的非法操作)
5. C++ 类的三大件(构造/析构/赋值)
- 如果类没有声明这三样,编译器自动生成默认版本
- 赋值函数必须:①检查自赋值 ②delete 原有资源 ③拷贝 ④返回
*this - 析构函数禁止抛异常
- 构造函数调用虚函数不会有多态效果
- 拷贝构造与赋值函数的区别在”对象是否已存在”
6. 继承与组合的准则
- 多用组合、慎用继承(“public 继承是一种 is-a 关系”,只有真 is-a 才继承)
- 派生类的析构/拷贝会先调用基类对应函数
- 只有基类的
virtual函数才有覆写意义;避免遮蔽(overwriting)同名非虚函数
7. 其它编程经验
- 慎用全局变量、慎用
goto、慎用类型转换 - 宏定义技巧:参数和外层都加括号
#define SQUARE(x) ((x)*(x)),且宏名全大写 - 变量声明的位置要靠近使用处,作用域越小越好
- 运算符优先级记不清就加括号
经典面试样题(附录 A)
- 写出
BOOL与”零值”比较的if语句:if(!bTestFlag) - 写出 float 与零值比较:
if((f >= -EPSINON) && (f <= EPSINON))(不能f == 0.0) - 指针与零值比较:
if(p == NULL) sizeof(p)(数组名作参数退化为指针):题目中sizeof(p)恒为 4(32 位平台指针宽度)strcpy标准实现及为何返回char*:为实现链式表达式strlen(strcpy(dst, src))- 手写 String 类四大件(本书标准答案见上文规则)
可行动点
- 作为 C/C++ 代码 review 检查单:本文”表达式陷阱”和”内存错误”清单可直接用于 review 清单
- “三大件”模板可直接抄入新写的 C++03 风格裸管理类
- 对新人培训仍是有效材料(风格部分不因 C++11/17 过时;内存部分被 RAII/智能指针部分取代——第 7 章的教训在智能指针时代仍适用于裸指针边界)
关联
- Essential C++-中文版本导读 —— 同为 C++ 入门经典,Bruce Eckel 风格向,可与本指南”第 8-10 章 C++ 特性”对照
- UNIX网络编程卷2-进程间通信 —— 系统级 C 编程实战
- C++代码规范与Review清单
元信息
- 云盘路径:/田浩然上传的资料/1A004_C++程序设计/参考资料/C C++高质量编程.pdf(101 页,326 KB)
- 版本:v1.0 正式文件,2001-07-24
- 提取方式:pdftotext 兜底(pdf-inspector 判 text_based 但 markdown 输出为空,疑似字体编码自定义映射)