高质量C++编程注意事项

  • 不提倡使用全局变量,尽量不要在头文件中出现象extern int value 这类声明

  • 变量的名字应当使用“名词”或者“形容词+名词”

  • 全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)

  • 不可将布尔变量直接与TRUE、FALSE 或者1、0 进行比较

  • 不可将浮点变量用“==”或“!=”与任何数字比较

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

  • 如果循环体内存在逻辑判断,并且循环次数很大,宜将逻辑判断移到循环体的外面

  • 在C++ 程序中只使用const 常量而不使用宏常量,即const 常量完全取代宏常量

  • 需要对外公开的常量放在头文件中,不需要对外公开的常量放在定义文件的头部。为便于管理,可以把不同模块的常量集中存放在一个公共的头文件中

  • 不要将正常值和错误标志混在一起返回。正常值用输出参数获得,而错误标志用return 语句返回

  • 使用断言捕捉不应该发生的非法情况。不要混淆非法情况与错误情况之间的区别,后者是必然存在的并且是一定要作出处理的

  • 用free 或delete 释放了内存之后,立即将指针设置为NULL,防止产生“野指针”

  • 当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针
  • 对于32 位以上的应用程序而言,无论怎样使用malloc 与new,几乎不可能导致“内存耗尽”
  • 成员函数被重载的特征:

    • 相同的范围(在同一个类中);

    • 函数名字相同

    • 参数不同

    • virtual 关键字可有可无

  • 覆盖是指派生类函数覆盖基类函数,特征是:

    • 不同的范围(分别位于派生类与基类)

    • 函数名字相同

    • 参数相同

    • 基类函数必须有virtual 关键字

  • 隐藏是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

    • 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)

    • 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)

  • 在 C++运算符集合中,有一些运算符是不允许被重载的。这种限制是出于安全方面的考虑,可防止错误和混乱

    • 不能改变C++内部数据类型(如int,float 等)的运算符。

    • 不能重载‘.’,因为‘.’在类中对任何成员都有意义,已经成为标准用法

    • 不能重载目前C++运算符集合中没有的符号,如#,@,$等。原因有两点,一是难以理解,二是难以确定优先级

    • 对已经存在的运算符进行重载时,不能改变优先级规则,否则将引起混乱

  • “缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方式来实现,倘若类中含有指针变量,这两个函数注定将出错

  • 如果类存在继承关系,派生类必须在其初始化表里调用基类的构造函数

  • 类的const 常量只能在初始化表里被初始化,因为它不能在函数体内用赋值的方式来初始化

  • 成员对象初始化的次序完全不受它们在初始化表中次序的影响,只由成员对象在类中声明的次序决定

  • 如果类A 和类B 毫不相关,不可以为了使B 的功能更多些而让B继承A 的功能和属性

  • 若在逻辑上B 是A 的“一种”,并且A 的所有功能和属性对B 而言都有意义,则允许B 继承A 的功能和属性

  • 若在逻辑上A 是B 的“一部分”(a part of),则不允许B 从A 派生,而是要用A 和其它东西组合出B

  • 如果输入参数采用“指针传递”,那么加const 修饰可以防止意外地改动该指针,起到保护作用

  • 如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰

  • 如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值

  • 不要一味地追求程序的效率,应当在满足正确性、可靠性、健壮性、可读性等质量因素的前提下,设法提高程序的效率

  • 以提高程序的全局效率为主,提高局部效率为辅

  • 在优化程序的效率时,应当先找出限制效率的“瓶颈”,不要在无关紧要之处优化。

  • 先优化数据结构和算法,再优化执行代码

  • 有时候时间效率和空间效率可能对立,此时应当分析那个更重要,作出适当的折衷。例如多花费一些内存来提高性能。

  • 不要追求紧凑的代码,因为紧凑的代码并不能产生高效的机器码。

  • 当心那些视觉上不易分辨的操作符发生书写错误。我们经常会把“==”误写成“=”,象“   ”、“&&”、“<=”、“>=”这类符号也很容易发生“丢1”失误。然而编器却不一定能自动指出这类错误。
  • 变量(指针、数组)被创建之后应当及时把它们初始化,以防止把未被初始化的变量当成右值使用。

  • 当心变量的初值、缺省值错误,或者精度不够。

  • 当心数据类型转换发生错误。尽量使用显式的数据类型转换(让人们知道发生了什么事),避免让编译器轻悄悄地进行隐式的数据类型转换。

  • 当心变量发生上溢或下溢,数组的下标越界。

  • 当心忘记编写错误处理程序,当心错误处理程序本身有误。

  • 当心文件I/O 有错误。

  • 避免编写技巧性很高代码。

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

  • 如果原有的代码质量比较好,尽量复用它。但是不要修补很差劲的代码,应当重新编写。