改善C++代码的建议

学习C++代码的一些建议,记录一下

  • 不要让main函数返回void() —-int main()int main(int argc,char *argv[])这两个都是可行的;
  • FALSE/TRUE是int型,false/true是bool型
  • 表达式****==****,最好写成number==nValue,例0==nValue
  • 运算符优先级问题要考虑清楚
  • 使用宏定义时,要用括号完备地保护每一个参数
  • 指针变量一定要初始化
  • 将逗号分隔表达式一定要规范,在条件和循环语句中,表达式的值采用的是最右边的结果;
  • 时刻提防内存溢出。当信息来源不可靠时,要用到内存缓冲区时,必须提高警惕,必须知道内存缓冲区的总长度,并检验内存缓冲区;
  • 拒绝晦涩难懂的函数指针定义,拒绝函数定义中成堆的括号,使用typedef让函数指针更加直观,易维护;
  • 避免包含相同的头文件在不同文件中
{
   #ifndef _PROJECT_PATH_FILE_H_

   #define _PROJECT_PATH_FILE_H_
   ……//声明
   #endif 
};
  • 优化结构体中元素的布局
{
    a.结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
    b.结构体每个成员相对于结构体首地址的偏移量(offset)都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节;
    c.结构体的总大小为结构体最宽基本类型大小的整数倍,如有需要,编译器会在最末一个成员之后加上填充字节。
*把结构体中得变量按照类型大小从小到大依次声明,尽量减少中间的填充字节。
}
#pragma pack(1)
struct A
{
   int a;
   char b;
   short c;
}
  • 将强制转型减到最少 不同类型的指针之间不能相互转换(避免在内存访问时存在隐患)
    • const_cast(a):目的简单明确,使用情形比较单一,易于掌握;
    • dynamic_cast(a):实现慢,代价大;
    • reinterpret_cast(a):不安全;
    • static_cast(a):不安全
  • 优先使用前缀操作符 前缀操作符的效率要优于后缀操作符(整形,长整形可忽略;用户自定义类型,优先使用前缀操作符。)
  • 掌握变量定义的位置与时机 控制变量的作用域,适当位置可减少操作时间;
  • 小心typedef使用中的陷阱 容易与宏定义混淆,typedef声明多个指针对象,形式直观,方便省事。请注意区分typedef与#define之间的不同,不要用理解宏的思维方式对待typedef,typedef声明的新名字具有一定的封装性,更易定义变量。同时还要注意它是一个无“现实意义”的存储类关键字;
  • 尽量不要使用可变参数 缺乏类型检查,类型安全性无从谈起;必须通过其他方式告诉函数所传递的类型,以及参数个数;不支持自定义数据类型;
  • 慎用goto 没有带来太大的正面作用,相反却容易破坏程序的结构性,影响了程序的可读性;
  • 提防隐式转换带来的麻烦 影响数据的精确性,编译器无法正常接受;(为防止精度损失,类型总是被提升为较宽的类型;所有含有小于整形的算术表达式在计算之前其类型都会被转换成整形)
    • 使用非C/C++关键字的具名函数,用operator as_T()替换operato T();
    • 为单参数的构造函数加上explicit关键字;
  • 正确区分void与void 如果函数没有返回值,那么应将其声明为void类型(不加返回值类型限定的函数,就会被编译器作为返回整型值处理);如果函数无参数,那么声明函数参数为void;任何类型的指针都可以赋值给void*;void指针进行算法操作是不合法的;
  • 明白在C++中如何使用C 要想在C++中使用大量现成的C程序库,实现C++与C的混编,必须了解extern“C”是怎么回事,明白“C”的使用方式;
  • 使用memcpy()系列 包含memcpy(),memset(),memcmp(),要注意对象是不是POD。
  • 尽量用new/delete代替malloc/free malloc/free是语言的标准函数库,而new/delete是C++的运算符。malloc/free无法满足创建动态对象的要求;new不仅能够完成动态内存分配,还能完成初始化工作,稳妥的构造对象;delete不仅能完成内存的释放,还能对对象进行清理。
  • 灵活地使用不同风格的注释 版权和版本声明,使用C风格的/ \/;内嵌注释用//;宏尾端的注释用/ /
  • 尽量使用C++标准的iostream C++ iostream程序库中的类与C stream函数虽然各有优点,但是一般推荐使用前者,为类型安全与可扩充性对于我们更有吸引力,所以建议使用iostream;
  • 尽量采用C++风格的强制类型转换
  • 尽量用const、enum、inline替换#define 宏定义并不在编译范围内,使得程序难于分析,难于调试;使用常量可以避免目标码的多分复制;用const修饰指针建议使用更加高级的const string形式。对于简单的常量,应该尽量使用const对象或枚举类型的数据,避免使用#define。对于形似函数的宏,尽量使用内联函数,避免使用#define。尽量将工作交给编译器而不是预处理器;
  • 用引用代替指针 从编码实践角度来看,指针与引用并无太大不同。在大多数情况下,指针可用索引类型完美代替,并且其实现代码更简洁清晰,更加易于理解
  • 区分内存分配的方式 栈效率高一点,而堆较灵活
  • new/delete与new[]/delete[]必须配对使用
  • 区分new的三种形态
  • new内存失败后的正确处理 当使用new申请一块内存失败时,抛出异常std::bad_alloc是C++标准中规定的标准行为,所以推荐使用try{p=new int[SIZE];}catch(std::bad_alloc){…}的处理方式
  • 明晰class与struct之间的区别
    • 关于使用大括号初始化:class与struct定义了构造函数就不能用大括号初始化,如果没有定义struct可以用大括号初始化,而class只有在所有成员变量全是public情况下才能用大括号初始化;
    • class默认成员访问权限是private,struct中则是public
    • class继承是private,struct继承是public