C++编码规范——日积月累、持续更新

一、命名规范

每个公司都有不同的代码规范,列举两种比较常用的规范。
1.1 小驼峰式命名法(lower camel case):
第一个单词以小写字母开始,第二个单词的首字母大写。例如:firstNamelastName
1.2 大驼峰式命名法(upper camel case):
每一个单词的首字母都采用大写字母,例如:FirstName、LastName、CamelCase,也被称为Pascal命名法。变种:StudlyCaps,是“驼峰式大小写”的变种.

二、不确定的函数访问权限声明为私有

新增一个函数,在不确定其使用范围时,使用private限定。

  • 降低调用人查找外部接口的负担
  • 未使用的private函数可以被SonarQube检测出来,并列举到代码坏味道中,方便后续精简结构。
  • 保证类层次和封闭性

三、条件判断时常值放左边

条件判断等号==,在输入时肯可能因为键盘问题或其他不可控的疏忽,导致漏掉一个等号字符,成为正常的赋值语句。正常编译,运行时候错误难排查。因此要求将常值放在等号左边,即使漏掉一个等号,因常值无法赋值修改,编译期间会报错。

string strvalue = "loveyy"
//如果写成了(strvalue="loveyy"),变成赋值语句,不会报错
if(strvalue == "loveyy")
{
//..
}
//如果写成了("loveyy"=strvalue),会编译报错
if("loveyy" == strvalue)
{
//...
}

三、分支和循环后的单行语句置于花括号

if,else,for,while等分支和循环语句,后跟单行语句时,花括号虽然可以省略,但可能因为意想不到的宏展开导致错误,或由于后续维护增加代码和不当操作,引起其他错误。

//如果REPORT宏展开以后是多行,可能会引起错误
#define REPORT(value) \
	cout<<value<<endl;\
	cout<<value<<endl;
//错误写法		
if("lovepigyy" == str_Value)
	REPORT("PIGYUANYUAN");
//宏展开后
if("lovepigyy" == str_Value)
	cout<<"PIGYUANYUAN"<<endl;
	cout<<"PIGYUANYUAN"<<endl;
//正确写法	
if("lovepigyy" == str_Value)
{	REPORT("PIGYUANYUAN");}
//宏展开后
if("lovepigyy" == str_Value)
{
	cout<<"PIGYUANYUAN"<<endl;
	cout<<"PIGYUANYUAN"<<endl;
}

四、重写虚函数需要添加override关键字

在派生类中重写基类的虚函数,如果重写函数没有添加override关键字,在函数名称或参数书写错误的情况下,编译时,会创建一个新的虚函数,编译不报错,运行时,不能正确的实现动态多态,且在代码量大时很难定位,难以察觉。
派生类中的虚函数声明处,添加override关键字能够保证与父类的虚函数声明的一致性检查,确认其父类一定包含此虚函数,在不一致时候,会编译报错。

class Base
{
//...
protected:
 	virtual void Update();
};

class Derivated : public Base
{
//...
protected:
	virtual void Update() override;
}

五、 类成员变量在声明处设置默认值

类成员变量未定义,或因存在多种构造函数,在某次构造时忘记初始化,尤其是指针变量,很容易引起错误。
避免忘记初始化,在头文件变量声明处一定要赋值。

class My_CLass
{
//...
private:
	My_CLass1 *m_mylp{ nullptr };
	bool m_firstRead{ false };
}

六、 类析构函数中释放类型为指针的成员变量

避免内存泄露,程序运行越久,占用内存越大的问题。
struct除默认访问方式,继承方式以及关键字的用处不同,其他与class等价

class My_Class
{
//...
	~My_CLass()
	{
	 if(!ptr)
	 {
	 	delete ptr;
	 	ptr = nullptr;
	 }	
	}
//...
private:
	My_CLass* ptr{nullptr};
}

六、使用nullptr而不是NULL、0

参考链接爱编程的大饼

//底层代码:
#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

也就是说如果源码是 C++ 程序 NULL 就是 0,如果是 C 程序 NULL 表示 (void*)0。那么为什么要这样做呢? 是由于 C++ 中,void * 类型无法隐式转换为其他类型的指针,此时使用 0 代替 ((void *)0),用于解决空指针的问题。这个 0(0x0000 0000)表示的就是虚拟地址空间中的 0 地址,这块地址是只读的。
出于兼容性的考虑,C++11 标准并没有对 NULL 的宏定义做任何修改,而是另其炉灶,引入了一个新的关键字 nullptrnullptr 专用于初始化空类型指针,不同类型的指针变量都可以使用 nullptr 来初始化

void fun(int)
void fun(int*)
fun(nullptr);//调用fun(int *)
//如果是:
fun(NULL);//调用fun(int)

七、非基础类型参数传递尽量使用const修饰的引用

防止参数传递过程中多义词拷贝构造和析构,尽量使用const和引用

  • 避免拷贝构造构造造成额外的开销和程序效率变低。
  • 避免函数体中意外修改,编译时报错。
my_calss* Get_Name(const std::string & name);

注:基础类型的如(intfloat),不建议传递引用会导致效率更低,另外STL迭代器和函数对象也使用值传递。

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愿天堂没有C++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值