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

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

@[toc]

一、命名规范

每个公司都有不同的代码规范,列举两种比较常用的规范。
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迭代器和函数对象也使用值传递。

相关文章
|
3月前
|
C++
C++核心编程三:函数提高(持续更新)
C++核心编程三:函数提高(持续更新)
|
3月前
|
编译器 C++
C++核心编程二:引用(持续更新)
C++核心编程二:引用(持续更新)
|
3月前
|
程序员 编译器 C++
C++核心编程一:内存分区模型(持续更新)
C++核心编程一:内存分区模型(持续更新)
|
3月前
|
C++
C++基础学习:通讯录管理系统(持续更新)
C++基础学习:通讯录管理系统(持续更新)
|
4月前
|
网络协议 关系型数据库 MySQL
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
[mysql 基于C++实现数据库连接池 连接池的使用] 持续更新中
|
4月前
|
关系型数据库 MySQL C++
[mysql C++ 简单连接到深入] 持续更新中
[mysql C++ 简单连接到深入] 持续更新中
|
9月前
|
编译器 C语言 C++
【C/C++】从 C 到 C++ (持续更新)
从 C语言转到 C++ 需要注意的事项
67 1
|
11月前
|
安全 IDE 数据挖掘
C/C++中常用必会的专业单词(持续更新 目前165个)
C/C++中常用必会的专业单词(持续更新 目前165个)
163 0
|
11月前
|
C语言 C++
高质量C++ C编程指南及编码规范.pdf
高质量C++ C编程指南及编码规范.pdf
400 0
|
11月前
|
编译器 C语言 C++
【C++系列P1】带上这篇基础小宝典,进发C++!(持续更新ing~)
【C++系列P1】带上这篇基础小宝典,进发C++!(持续更新ing~)

相关实验场景

更多