高质量c/c++编程

第1章

为防止头文件被重复引用,应当用 ifndef/define/endif 结构产生预处理块

使用 #include<filename.h> 引用标准库头文件,使用 #include"filename.h" 引用非标准库头文件

头文件中只存放“声明”,不存放“定义”



第2章

应在关联性不强的语句间添加空行

一行代码只做一件事情

if、for、while、do 等语句自占一行,且必须带上 {}

尽可能在定义变量的同时初始化该变量

关键字后面要添加空格,函数明后不留空格

    for (int i = 0; i < 10; ++ i)

    int sum(int i)

修饰符 * 和 & 应紧靠变量名



第3章

程序中不要出现仅靠大小写区分的相似的标识符,不要出现标识符相同的局部变量和全局变量

类名和函数名用大写字母开头的单词组合,变量和参数用小写字母开头的单词组合,常量全用大写字母,并用下划线分割单词

静态变量前加 s_,全局变量前加 g_,类的数据成员加 m_



第4章

为防止产生歧义并提高可读性,应当使用括号来确定表达式的操作顺序

与零值比较时,布尔变量使用 if (flag)、整型变量使用 if (1 == num)、浮点型变量使用 if (x >= -eps && x <= eps)、指针变量使用 if (NULL == p)

在多重循环中,如果有可能,应当最长的循环放在最内层,已减少CPU跨切循环的次数

不可在for循环体内修改循环变量,防止 for 循环失去控制

不要遗漏了 switch 语句中的每个 case 语句后面的 break,不要遗漏 default 语句



第5章

用 const 常量完全取代宏常量

如果某一常量与其他常量密切相关,应在定义中包含这种关系

    const float RADIUS = 100;

    const float DIAMETER = RADIUS * 2;

类中的常量应使用枚举常量来实现,但要注意 enum 只能代表整数



第6章

函数的参数名要恰当,顺序要合理

如果函数参数是指针,且仅作输入用,应在类型前加上 const 以防止被无意修改

如果输入参数以值传递方式传递对象,则应用"const &"方式以省去临时对象的构造和析构过程

若函数没有参数,用void填充

若函数没有返回值,应声明为 bool 类型,并在函数体结尾 return true;

正常值用输出参数获得,而错误标志用 return 语句返回

在函数体的“入口处”,在必要时候要使用断言 assert 对参数的有效性进行检查

在函数体的“出口处”,要对 return 语句的正确性和效率进行检查,不可返回指向“栈内存”的指针或引用

函数功能要单一,不可带有“记忆”功能

函数的参数该用指针还是引用,要看函数对此参数的具体需求,“用适当的工具做恰如其分的工作”



第7章

内存分配的方式:

    1.静态存储区域分配,全局变量,static变量

    2.栈,局部变量

    3.堆,使用 malloc 或 new 申请的内存



使用了 malloc 或 new 后应该立即检查指针是否为 NULL

不要忘记为数组和动态内存赋初值

避免数组或指针的下标越界,特别当心“多1”或“少1”的情况

动态内存的申请和释放必须配对,防止内存泄露

使用 free 或 delete 释放内存后,应立即将指针置为 NULL,防止产生迷途指针



C/C++语言无法知道指针所指的内存容量,必须在申请内存时记住它

当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针

不能使用指针参数来申请内存,只能使用“指向指针的指针”参数申请内存,可以使用返回指针类型的函数申请内存

C++代码 复制代码
  1. char *GetString(void)   
  2. {   
  3.     char *p = "hello world";      //错误,"hello world"存储在静态存储区   
  4.     //char p[] = "hello world";   //错误,return 返回指向“栈内存”指针   
  5.     return p   
  6. }  


malloc/free 是标准库函数,new/delete 是运算符,malloc/free 无法动态创建自定义类类型对象,保留 malloc/free 主要是为了和 C 兼容

内存耗尽时(无法申请到内存),应马上使用 exit(1) 终止程序

若指针 p 非空,连续对 p 使用两次 free 会导致程序崩溃

用 delete 释放对象数组时要加上 []



第8章

当心隐式类型转换导致重载函数产生二义性

如果派生类的函数与基类的函数同名,但参数不同,此时,无论有无 virtual 关键字,基类的函数都将被隐藏

如果派生类的函数与基类的函数同名,且参数相同,但基类函数没有 virtual 关键字,基类的函数被隐藏

参数的缺省值只能出现在函数的声明中,而不能出现在函数的定义体中,不合理地使用参数缺省值将可能导致重载函数的二义性

inline不应该出现在内联函数的声明中,但必须出现在内联函数的定义中,应使用内联函数取代宏



第9章

对于任意的类,系统将自动为其产生构造函数、拷贝构造函数、析构函数和赋值函数,这四个函数最好自己定义,例如A a = b,a会自动调用拷贝构造函数,若A的构造函数中存在动态开辟内存的操作,则开辟内存的指针会在拷贝的时候复制,可是仅仅复制了指针的地址,但没有再次动态地开辟一次内存,这样a和b都存在一个指向同一空间的指针,当他们调用析构函数的时候,该内存空间就会被释放两次而产生错误,这种没有把内存资源拷贝多一份的现象称为“浅拷贝”

const常量只能在构造函数的初始化列表里被初始化

成员在初始化列表中的初始化顺序只由成员对象在类中声明的次序决定

拷贝构造函数可以调用本类的私有成员

C++代码 复制代码
  1. String::String(const String &other)   
  2. {   
  3.     int len = strlen(other.m_data);   
  4.     m_data = new char[len + 1];   
  5.     strcpy(m_data, other.m_data);   
  6. }  



赋值函数

C++代码 复制代码
  1. String & String::operate =(const String &other)   
  2. {   
  3.     if (this == &other)   
  4.         return *this;   
  5.   
  6.     delete [] m_data;   
  7.   
  8.     int len = strlen(other.m_data);   
  9.     m_data = new char[len + 1];   
  10.     strcpy(m_data, other.m_data);   
  11.   
  12.     return *this;   
  13. }  




为了防止内存泄露,析构函数必须为虚函数

派生类的构造函数必须在其初始化列表中调用基类的构造函数

编写派生类的赋值函数时,要记得对基类的数据成员重新赋值



第10章

只有在逻辑上B是A的“一种”,且A的所有功能和属性对B都有意义,才允许B继承A的功能和属性



第11章

多使用 const 提高函数的健壮性

小心数据类型发生隐式转换

避免编写技巧性很高的代码

不要设计面面俱到、非常灵活的数据结构

尽量使用标准库,不要“发明”已经存在的库函数

尽量不要使用与具体硬件或软件环境关系密切的变量

目 录 前 言6 第1 章 文件结构 1.1 版权和版本的声明. 1.2 头文件的结构. 1.3 定义文件的结构. 1.4 头文件的作用. 1.5 目录结构. 第2 章 程序的版式 2.1 空行. 2.2 代码行. 2.3 代码行内的空格. 2.4 对齐. 2.5 长行拆分. 2.6 修饰符的位置. 2.7 注释. 2.8 类的版式. 第3 章 命名规则 3.1 共性规则. 3.2 简单的WINDOWS 应用程序命名规则. 3.3 简单的UNIX 应用程序命名规则 第4 章 表达式和基本语句 4.1 运算符的优先级. 4.2 复合表达式. 4.3 IF 语句 4.4 循环语句的效率. 4.5 FOR 语句的循环控制变量. 4.6 SWITCH 语句. 4.7 GOTO 语句. 第5 章 常量 5.1 为什么需要常量. 5.2 CONST 与 #DEFINE 的比较. 5.3 常量定义规则. 5.4 类中的常量. 第6 章 函数设计 高质量C++/C 编程指南,v 1.0 2001 Page 4 of 101 6.1 参数的规则. 6.2 返回值的规则. 6.3 函数内部实现的规则. 6.4 其它建议. 6.5 使用断言. 6.6 引用与指针的比较. 第7 章 内存管理 7.1 内存分配方式 7.2 常见的内存错误及其对策 7.3 指针与数组的对比 7.4 指针参数是如何传递内存的? 7.5 FREE 和DELETE 把指针怎么啦? 7.6 动态内存会被自动释放吗?. 7.7 杜绝“野指针”. 7.8 有了MALLOC/FREE 为什么还要NEW/DELETE ?. 7.9 内存耗尽怎么办?. 7.10 MALLOC/FREE 的使用要点 7.11 NEW/DELETE 的使用要点. 7.12 一些心得体会 第8 章 C++函数的高级特性 8.1 函数重载的概念. 8.2 成员函数的重载、覆盖与隐藏. 8.3 参数的缺省值. 8.4 运算符重载. 8.5 函数内联. 8.6 一些心得体会. 第9 章 类的构造函数、析构函数与赋值函数 9.1 构造函数与析构函数的起源. 9.2 构造函数的初始化表. 9.3 构造和析构的次序. 9.4 示例:类STRING 的构造函数与析构函数 9.5 不要轻视拷贝构造函数与赋值函数. 9.6 示例:类STRING 的拷贝构造函数与赋值函数 9.7 偷懒的办法处理拷贝构造函数与赋值函数. 9.8 如何在派生类中实现类的基本函数. 9.9 一些心得体会. 第10 章 类的继承与组合. 高质量C++/C 编程指南,v 1.0 2001 Page 5 of 101 10.1 继承 10.2 组合 第11 章 其它编程经验. 11.1 使用CONST 提高函数的健壮性 11.2 提高程序的效率 11.3 一些有益的建议 参考文献 附录A :C++/C 代码审查表. 附录B :C++/C 试题. 附录C :C++/C 试题的答案与评分标准.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值