C++ 编码规范(个人整理)

1.对动态内存分配失败的情况进行检查
当分配请求的内存空间失败时,标准的malloc函数返回NULL指针。标准C++的new操作符会抛出std::bad_alloc异常,new操作符的nothrow形式失败时则返回NULL。

/*正确案例*/

/*C正确的检查分配失败情况*/
int *my_ptr;
my_ptr=(int*)malloc(sizeof(int)*elem_num);
if(my_ptr==NULL)
{
    /*内存分配失败情况的处理*/
}

/*C++正确的检查分配失败情况*/
try
{
    int *pn=new int;
    double *pd=new double(50.5);
    int *buf=new int[20];
}
catch(std::bad_alloc)
{
    /*内存分配失败情况的处理*/
}

/*C++的nothrow形式*/
int *pn=new(nothrow)int;
if(pn==NULL)
{
/*内存分配失败情况的处理*/
}

2.在free或delete释放指针后,立即为指针置为NULL值(清除指针值),防止产生“野指针”。
动态内存的申请与释放必须配对,防止内存泄露。
3.在程序块的结束行右方加注释标记,以表明某程序块的结束。
【说明】:当代码段较长,特别是多重嵌套时,这样做可以使代码更清晰,更便于阅读。

if(...)
{
    /*program code*/
    while(index<MAX_INDEX)
    {
    /*pragram code*/
    }/*end of while(index<MAX_INDEX)*/
}/*end of if(...)*/

4.用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。
【说明】:下面是一些在软件中常用的反义词组。

add/remove    begin/end    create/destroy    
insert/delete    first/last    get/release
increment/decrement    put/get    add/delete    
lock/unlock    open/close    min/max
old/new    start/stop    next/previous    
source/target    show/hide    send/receive
source/desination    cut/paste    up/down

5.除了变异开关/头文件等特殊应用,应避免使用_EXAMPLE_TEST_之类以下划线开始和结尾的定义。
6.源文件头部应进行注释,列出:版权说明、头文件、修改日志等。
7.函数头部应进行注释,注释格式按下列两种示例之一即可。
8.switch语句必须有default分支。
9.在多重循环中,应将最忙的循环放在最内层。
【说明】:减少CPU切入循环层的次数。

/*如下代码效率不高*/
for(row=0;row<100;row++)
{
    for(col=0;col<5;col++)
    {
        sum+=a[row][col];
    }
}

/*如下形式效率较高*/
for(col=0;col<5;col++)
{
    for(row=0;row<100;row++)
    {
        sum+=a[row][col];
    {
}

10.尽量用乘法或其他方法代替除法,特别是浮点运算中的除法。
【说明】:浮点运算除法要占用较多CPU资源。

/*如下表达式运算可能要占用较多的CPU资源*/
#define PI 3.1416
radius=circle_length/(2*PI);

/*应如下把浮点除法改为浮点乘法。*/
#define PI_RECIPROCAL (1/3.1516) //编译时,将生成具体浮点数
radius=circle_length*PI_RECIPROCAL/2;

11.严禁局部变量与全局变量同名。
12.严禁使用未经初始化的变量作为右值。
13.使用变量时要注意其边界值的情况。
【说明】:如C语言中字符型变量,有效值范围为-128~127。故以下表达式的计算存在一定风险。

char chr=127;
int sum=200;

14.减少函数本身或函数间的递归调用。
【说明】:递归调用特别是函数间的递归调用(如A->B->C->A),影响程序的可理解性;递归调用一般都占用较多的系统资源(如栈空间);递归调用对程序的测试有一定影响。故除非为某些算法或功能的实现方便,应减少没必要的递归调用。
15.设计高扇入、合理扇出(小于7)的函数。
【说明】:扇出是指一个函数直接调用(控制)其他函数的数目,而扇入是指有多少上级函数调用它。较良好的软件结构通常是顶层函数的扇出较高,中层函数的扇出较少,而底层函数则扇入到公共模块中。
16.用宏定义表达式时,要使用完备的括号。

/*如下定义的宏都存在一定的风险。*/
#define RECTANGLE_AREA(a,b) a*b
#define RECTANGLE_AREA(a,b) (a*b)
#define RECTANGLE_AREA(a,b) (a)*(b)
/*正确的定义应为:*/
#define RECTANGLE_AREA(a,b) ((a)*(b))

17.使用宏时,不允许参数发生变化。

/*如下用法可能导致错误。*/
#define SQUARE(a) ((a)*(a))
int a=5;
int b=SQUARA(a++);    //结果a=7,即执行了两次增1。

/*正确的用法是:*/
b=SQUARA(a);
a++;    //结果a=6,即只执行了一次增1。

18.不允许包含无用的头文件,不要重复包含头文件。
19.仅在一个C/CPP文件中使用的结构可以不放在头文件中,直接放在C/CPP文件中。
20.路径使用斜线“/”,而不是反斜线“\”,“/”能被不同的平台识别。

#include "./NetPreview/PreviewEngine.h"

21.标识符的命名要清晰、明了,有明确的含义。
【说明】:使用完整的单词或众所周知的缩写,避免使人产生误解。较短的单词可通过去电“元音”形成缩写;较长的单词可取单词的头几个字母形成缩写,一些单词有大家公认的缩写,例如:

temp -> tmp
flag -> flg
statistic -> stat
increment -> inc
message -> msg

22.全局变量使用static定义,访问全部变量使用Get()、Set(),尽量避免使用extern。
23.常亮使用宏定义。
24.判断指针是否为空,建议直接与“NULL”或“nullptr”,而不是使用“!”。
25.在同一项目组或产品组内,要有一套统一的为集成测试与系统联调准备的调试开关及相应打印函数,而且要有详细的说明。
26.正式软件产品中应把断言及其他调试代码去掉(即把有关的调试开关关掉),加快软件运行速度。
27.用调测开关来切换软件的DEBUG版和正式版。而不要同时存在DEBUG版和正式版本的不同源文件,以减少维护的难度。
28.在没有检查索引是否超过边界的情况下,禁止使用std::string::operator[];如果对效率要求不高,因使用std::string::at()方法。
【说明】:为了保证效率,std::string::operator[]不执行边界检查,在索引超过边界的情况下不会抛出异常,从而可能导致缓冲区溢出。
29.将栈缓冲区重新声明为全局静态变量或者局部静态变量,降低栈粉碎攻击的可能性。
【说明】:关键局部变量改为全局变量或用static修饰,变量存储在内存数据段中,程序无法通过缓冲区溢出漏洞进行变量改写。
30.静态调用函数,而不是使用函数指针调用函数。防止函数指针无效或被篡改,导致异常。
【说明】:通过静态调用函数,而不是函数指针的形式进行函数调用,可以避免函数指针被篡改导致无效或者别攻击者覆写导致转移程序控制权。
31.加锁待程序块处理完必须解锁
【说明】:如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
32.当读操作远大于写操作时, 应该使用读写锁来进行同步。
【说明】:在一些写操作比较多或是本身需要同步的地方并不多的程序中,我们应该使用互斥量,而在读操作远大于写操作的一些程序中我们应该使用读写锁来进行同步。
33.使用自动代码块加解锁方案,如LockGuard。
【说明】:手动解锁在代码维护的过程中可能存在因为增加代码分支等情况造成没有解锁的问题,使用自动加解锁方案可以有效避免这种情况发生。
34.用内联函数或静态函数代替与函数相似的宏。
【说明】:当内联函数和宏可以相互使用时,应该优先选择内联函数。内联函数调用速度快且不会有歧义。
35.使用操作符sizeof确定类型或变量的长度可以提高代码的清晰性,并保证编译器或版本的变化不会影响代码。
36.不要认为结构的长度等于它的各个成员的长度之和。
37.注意逻辑AND和OR操作符的短路行为。
【说明】:逻辑AND和逻辑OR操作符(分别是&& 和||)采用“短路”操作、也就是说,如果对第一个操作数求值之后就可以推断出最终结果,第二个操作数就不会进行求值。
38.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值