C++ 编程风格建议

少于 1 分钟阅读

C++ 编程风格建议

安全

  1. 引用和指针
    • 引用不会为空
    • 引用不会改变指向
    • 引用不能进行+、-、++、–运算
  2. 宏定义多条语句
    • 使用do…while(false)来包含
  3. 逻辑符号||的执行 假设我们要同时自增a和b,如果任意一个函数失败了,则执行某些操作 Bad if(!IncreaseA() || !IncreaseB()) 假设自增A函数失败了,则不会自增B Good 分开写
  4. 尽可能缩短变量的存活时间
    • 短的变量存活时间减少了初始化错误的可能
    • 阅读者同一时间需要阅读的代码变少,便于理解
    • 当需要把一个大的函数分拆,短的存活时间方便拆分
  5. 避免浮点数的数量级相差巨大的数字之间的四则运算 double d = 100000000.0 + 0.1;
  6. 避免浮点数的等量比较
  7. if/循环语句必须使用大括号
  8. 禁止通过声明的方式引用外部函数接口、变量 通过extern声明的方式使用外部函数接口、变量,容易在外部接口改变时可能导致声明和定义不一致。
  9. 类的成员变量必须显式初始化
  10. 基类的析构函数必须声明为virtual
  11. 禁止虚函数使用缺省参数值
  12. 禁止重新定义继承而来的非虚函数
  13. 不允许使用宏来表示常量
    • 宏是简单的文本替换,在预处理阶段时完成,运行报错时直接报相应的值
    • 跟踪调试时也是显示值,而不是宏名
    • 宏没有类型检查,不安全
    • 宏没有作用域
  14. 禁止用memcpy_s、memset_s初始化非POD对象
    • POD类型主要包括int, char, float, double, enumeration, void, pointer等原始类ing以及聚合类型,不能使用封装和面向对象特性(如用户定义的构造/赋值/析构函数、基类、虚函数)
    • 由于非POD类型比如非聚合类型的class对象,可能存在虚函数,内存布局不确定,跟编译器有关,滥用内存拷贝可能会导致严重的问题。
    • 即使对聚合类型的class,使用直接的内存拷贝和比较,破坏了信息隐蔽和数据保护的作用,也不提倡使用memcpy_s、memset_s
  15. 含有变量自增或自减运算的表达式中禁止再次引用该变量 x = b[i] + i++;
  16. 不要保存std::string的c_str()返回的指针
  17. 对于指针和引用类型的形参,如果是不需要修改的,请使用const
  18. 使用强类型参数,避免使用void*
  19. 使用std::string代替char*
    • 不用考虑结尾的’\0’
    • 可以直接使用+, =, ==等运算符以及其他字符串操作函数
    • 不需要考虑内存分配操作,避免了显式的new、delete, 以及由此导致的错误

效率

  1. 循环嵌套, 把大循环写在里面

  2. strcmp的判断 Bad if(!strcmp(str1, str2)) Good if(strcmp(str1, str2) == 0)
  3. 肯定语句比双重否定容易理解 Good if(SomethingDone) Bad if(!NotDone)

  4. 条件判断语句 常量在右,变量在左 让编译器去检查误赋值的情况
  5. 使用小括号,避免优先级问题 Bad if(a < b == c == d) Good if((a < b) == (c == d))
  6. 为变量指定唯一用途。避免采用不同取值区间来区分不同内容, 如,Account小于5000时表示老用户ID,大于5000时表示新用户ID
  7. 避免采用硬编码
  8. 布尔变量的命名
    • 避免采用status、sourcefile等模糊的布尔变量名,采用statusOK、sourcefileFound
    • 避免采用否定形式的布尔变量 if(!NotSuccess)
  9. 避免在变量名中使用数字
    • 考虑使用数组代替
    • 如果数组不适合,那么数字更不适合
  10. 定义变量的作用域
    • 开始采用最严格的可见性,然后根据需求扩展变量的作用域
    • 循环内的变量挪动到循环外,比反过来简单
    • 把private变量变为public, 比反过来简单
  11. 不用的代码段直接删除,不要注释掉
    • 被注释掉的代码,无法被正常维护;当企图恢复使用这段代码时,极有可能引入容易被忽略的缺陷
    • 使用版本控制来,记录代码。
  12. 避免在变量名中使用容易混淆的字符
    • 数字1和小写的l
    • 数字1和大写的L
    • 数字0和大写的O
    • 数字2和小写的z
    • 数字6和大写的G
  13. 为空语句创建一个DoNothing()预处理宏或者内联函数
  14. 避免函数过长,函数不超过50行(非空非注释)
    • 函数应该可以一屏显示完(50行以内), 只做一件事情,而且把它做好。
    • 过长的函数往往意味着函数功能不单一,过于复杂,或过分呈现细节,未进行进一步抽象。
    • 即使一个长函数现在工作的很好,一旦有人对其修改,有可能出现新的问题,甚至导致难以发现的BUG。建议将其拆分为更加简短并易于管理的若干函数,以便于他人阅读和修改代码。

更新时间: