公司C++规范学习

语法部分

  • class和struct关键字的选择:class表示被封装的用户自定义类型,不公开定义非静态数据成员,struct表示数据的简单集合,只定义用于初始化数据成员的方法。
  • 必须使用构造函数初始化列表显示初始化直接基类与所有基类类型数据成员。
  • 没有复制意义的类必须用DISALLOW_COPY_AND_ASSIGN宏禁止拷贝构造函数和赋值构造函数。
    • DISALLOW_COPY_AND_ASSIGN 宏就是将复制拷贝函数和赋值操作符声明为私有变量。
  • 禁止在构造函数中进行可能出错的复杂操作(比如申请资源),复杂操作用额外的init()函数实现。
  • 显式初始化能够使代码更清晰、不易错误调用,还能避免二次赋值造成的效率问题, 单参构造函数尽量加上explicit。
  • 有默认值语义的类必须显示定义默认构造函数。
  • 没有默认值语意的类,必须显式定义其它构造函数或 private 声明默认构造函数,并不给出实现。
  • 如果类型是可拷贝,一定要同时定义拷贝构造函数和赋值构造函数,如果类型可移动,一定要同时定义移动构造函数和移动赋值函数。
    • 如果使用默认的拷贝和移动操作,要使用=default定义。
    • 如果类型不需要拷贝、移动操作,要使用=delete手段禁用。
    • 向容器添加数据时,优先使用emplace开头的接口函数。
  • 在极少的情况下,当该类的隐式转换很有意义时,可以不把单参数构造函数声明为显式构造函数,但必须十分小心,并使用文档化注释说明。
  • 单参数构造函数如果不用explicit关键字修饰,则可能被编译器用来做隐式类型转换。
  • 有复制意义的类必须显式给出复制构造函数,并小心指定其行为(浅复制、深复制等)
    • 托管了资源的类,往往是没有复制意义的。此时应当防止用户错误调用而导致资源泄漏、重复释放的后果。
    • 编译器默认生成的复制构造函数,对指针数据成员使用浅复制策略,但这种策略常常不是程序员希望的。
  • 析构函数:
    • 若类定义了虚函数,必须定义虚析构函数。
    • 若类设计为可被继承的,应该定义公开的虚析构函数或保护的非虚析构函数。
    • [RULE010] (不包括结构)含有指针成员,必须显式给出析构函数,并小心指定其行为(是否销毁指针,如何销毁等).
    • 绝不允许让异常离开析构函数。
  • 按照 public、protected、private 的顺序声明成员。按照类型、方法、数据成员的顺序声明成员, DISALLOW_COPY_AND_ASSIGN 放在 private 区段的末尾.
  • 不是非常必要的话,避免使用友元: 友元破坏了类的封装性,增加了类之间的耦合,适宜使用友元的如容器与它的迭代器,类与涉及该类的.
  • 委派和继承构造函数是由 C++11 引进为了减少构造函数重复代码而开发的两种不同的特性. 通过特殊的初始化列表语法, 委派构造函数允许类的一个构造函数调用其他的构造函数.
  • C++11强类型枚举enum class Side
  • 被重载的虚函数通过override显示声明.
  • 禁止被重载的函数通过final显示禁止.
  • Lambda表达式:
    • 不使用默认捕获(包括&, =), 捕获显示写出来.
  • 只在两种情况下使用右值引用, 一种是定义类型的移动操作函数时, 另一种是定义模板函数实现完美转发的时候. 除此之外, 不要使用右值引用.
    • 右值引用的语义比较复杂, 不恰当的使用会造成很难追查的bug.
  • 建议 include 的路径、文件名与命名空间保持一致
  • 使用空格缩进,不使用制表符。 以 4 个空格为单位缩进。避免超过 5 重的缩进。
  • 建议不要使用异常,除非已有项目/底层库使用了异常, 这时候必须要catch所有异常。
  • 所有代码应该定义在namespace中, main函数除外。
  • 禁止内联(inline)虚函数,inline函数应该在10行以内。
  • 函数静止使用默认参数,模板可以使用默认参数。-- 默认参数是编译期绑定的,不具有多态性。
  • 使用 auto 自动推导类型, 只能定义局部变量(返回类型后置声明除外).
  • 禁止使用 auto_ptr. 如果需要传递对象, 使用std::unique_ptr明确所有权传递. 如果要共享所有权, 使用std::shared_ptr明确所有权共享.
  • [RULE033] 避免对浮点数进行相等或不等比较。
    • 避免使用非布尔型的变量或表达式作为分支语句条件。
    • 作相等比较时,建议把常量或右值变量放在 == 运算符的右边。
  • 除非用于条件编译、跟踪调试,或者能够显著减少代码量并确保可读性的宏(如 DISALLOW_COPY_AND_ASSIGN, CFATAL_LOG etc.),否则不应使用。
  • 鼓励使用前向声明,以减少文件之间的依赖关系。
  • 尽可能避免使用全局变量,如有必要应使用 singleton 模式代替。
    • 内部使用的全局函数/变量,必须声明为静态函数、变量,不能在目标文件中出现外部可见的符号。
  • 不应在头文件定义类/结构体类型的全局常量,以减少代码膨胀。
  • 可能用于跨模块间通讯或者涉及存储的枚举值必须显式指定值,避免版本不一致造成诡异的错误。
  • const 关键字用在类型名前面而非后面。
    • 不修改内部状态的成员方法必须声明为 const
    • 返回不可修改的指针或引用必须声明为 const
    • 不被修改的引用/指针形参必须声明为 const
    • 除非保证状态不会被修改,不应使用 const_cast 来去掉 const 属性
  • 避免定义超过 4 KB 的局部变量数组

风格/约定

  • 必须按以下顺序引用头文件,并进行分节:.cpp 对应的头文件(如果有, // 优先位置), C(标准)库,C++(标准)库,其它库,自己项目的.h文件,每节内的include按照字母序。
  • 分行与空格:
    • 一条单独的语句必须独立成行。
    • 避免连续的空行。
    • 使用适当的空行来分组代码的逻辑。
    • 左大括号不独立,右大括号独立成行。并且左大括号所在行进行垂直对齐。
  • 命名空间不缩进。
  • 构造函数初始化列表放在同一行或按至少八格缩进并排几行, 如果需要换行, 把: 放在第一行。
  • 比较短的函数声明,整个声明占一行;过长的函数声明,令每一参数占一行,并且垂直对齐, 换行后的参数至少保持 8 个空格缩进。
  • 比较短的函数调用语句,整个语句占一行;过长的函数调用,控制折行确保每行不要超过 100 列,换行后至少额外缩进 8 个空格。
  • 空格的使用:
    • if/switch/while/for/catch 与后边的圆括号之间加一个空格,圆括号内侧与判断表达式之间不加空格。
    • for语句圆括号内分号前不加空格,分号后加一个空格。
    • 函数调用中,函数名和圆括号之间不要加空格。
    • 类继承与构造函数的初始化列表的冒号前后加一个空格。
    • 逗号表达式或参数列表中,逗号前不加空格,逗号后加一个空格。
    • 一元运算符前后不加空格。二元、三元表达式前后各加一个空格。
    • 成员访问或作用域运算符前后不加空格。如:a.b, a->b, a.b, a->b, a::b。
    • 圆括号和方括号运算符前后和内部都不加空格。
  • .h 中不要定义复杂的函数, 复杂函数如果必须在头文件中, 应该放在 .hpp 后缀的头文件中。
  • 没有使用到的函数参数,把参数名注释起来, 不允许未命名参数出现。
    • :函数的参数顺序,建议先安排输入参数,再安排输出参数。
    // 输入参数对象类型使用const引用
    void foo(const std::string& input1, const MyClass& input2);

命名规范

  • 全局可见的,却又无法通过命名空间约束的标识符命名,必须以库名作为前缀,以避免冲突。

  • 命名应当尽可能有描述性,不使用非通用的缩写(尤其是省一个字符的缩写如creat,usr等),不使用有歧义的缩写,不使用任意的无意义的字符.

  • 标识符的作用域越大,命名就应该越清晰。

  • 可能使用多个单位名称的变量(如表示时间的变量),应以单位名称缩写为后缀。

  • 文件名全部用小写字母, 中间用_间隔; 比如: this_is_my_awesome_file.cpp.

  • 单元测试文件名使用<被测文件名>_test.h(.cpp)命名.

  • 如果是要发布供它人使用的 lib,推荐仅暴露一个以库名同名,或者<库名>_<功能集合>.h的 api 头文件,然后将相关头文件 include 到这个 api 头文件中。如:mylib.h,mylib_utils.h,mylib_api.h。

  • 使用下划线分隔的全小写命名法命名命名空间。

  • 命名空间名可以使用缩写,同时应保证简短、不易冲突但同时富有意义。

  • 函数命名使用下划线分隔的全小写命名法。

  • 函数通常使用动词短语命名。

  • 自定义类类型使用首字母大写的驼峰命名法命名,一般不使用前缀。

  • 枚举类型成员,使用全大写蛇形命名法(即全部字母大写,单词间用下划线分隔)。

  • 尽可能不使用全局变量,如果必须使用,必须以g为前缀,而且必须足够长以避免名字冲突。

  • 全局变量使用下划线分隔的全小写命名法命名。

  • 局部变量名使用下划线分隔的全小写命名法命名。

    • 假如局部变量作用域很小,可以适当使用缩写。
  • 全局静态变量 s_ 作为前缀。类静态成员使用 s 前缀的下划线分隔的全小写命名法命名。

  • const 常量与枚举常量都使用下划线分隔的全大写命名法命名

  • 确定需要不同大小的变量,推荐使用<stdint.h>中定义的长度明确的整形类型,例如 int64_t, int32_t 等。

  • 多行注释必须写在被解释内容的上方。单行注释可以写在被注释语句的上文或右方。

  • 一行内只应声明一个变量。

  • 局部变量应尽量延迟到第一次使用处声明。

  • 局部变量应在声明处赋初值,指针类型局部变量必须在声明处赋初值。

  • 本规范不适用于引入的公司外第三方代码, 修改时请遵守第三方代码自身的编码风格。

  • 显式或者通过宏等隐式的定义派生自第三方代码中所申明的类,必须遵守对应第三方代码自身的编码风格。

公司C++规范学习的更多相关文章

  1. 阿里java开发规范学习(附P3C IDEA插件 帮助规范的养成)

    浅析 阿里巴巴 Java 开发规约 (未完成) 更加优秀的页面展现请到浅析 阿里巴巴 Java 开发规约 contents 为什么要学 编程规约 P3C IDEA 插件 why-use 我们知道,一般 ...

  2. W3C规范学习

    w3c:万维网联盟(World Wide Web Consortium,W3C),又称W3C理事会.W3C组织是对网络标准制定的一个非赢利组织,W3C是万维网联盟的缩写,像HTML.XHTML.CSS ...

  3. AMD规范学习笔记

    背景 NodeJS的一套比较简洁 Moudles 规范, 使得在服务器端的模块化变得更加简单.很长一段时间,很多公司或者项目都有自己的一套模块化机制, 却未能形成一套统一的标准, NodeJS的Mou ...

  4. NFC规范学习之一 ---整体结构

    1.NFC 采用两个感应线圈进行数据交互,其中至少必须有一个设备产生13.56MHZ的磁场,该场被调制以方便数据传输.通讯中,一个设备处于initiator模式(就是发起通讯)另外一个设备则工作在ta ...

  5. 公司需求知识学习-WCF

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  6. SpringCloud入门之YAML格式文件规范学习

    1. 认识 YAML YAML(发音 /ˈjæməl/)是一个类似 XML.JSON 的数据序列化语言.其强调以数据为中心,旨在方便人类使用:并且适用于日常常见任务的现代编程语言.因而 YAML 本身 ...

  7. Web Components 规范学习

    最新的规范在这里:http://w3c.github.io/webcomponents/explainer/ 依据规范,有以下四个组成部分: Templates Custom Elements Sha ...

  8. PSR规范学习笔记

    PSR已经经历了5次变革,如今PSR4就是最新的标准,但是还是有必要了解下5个版本的内容的,于是去php-fig网站看了下英文原版: 大概看了遍,发现这规范很多的必须很多时候只是建议,但是PHP解析器 ...

  9. JSR133规范学习

    最近在看多线程相关的东西,通过阅读JSR133的faq来加深自己对多线程的理解,里面大部分的内容比较简单(越到后面越难),但是有的部分比较难以理解还没有完全弄懂,所以这里只记录了一下比较简单的阅读笔记 ...

随机推荐

  1. 只要三步,你就可以在github上发布网站了

    今天,看到github推送了一个新的消息,Publishing with GitHub Pages, now as easy as 1, 2, 3.总结起来就是在github将你的文档或者发布网页将会 ...

  2. Thymeleaf简介

    Thymeleaf Thymeleaf简介 Thymeleaf是一个流行的模板引擎,该模板引擎采用Java语言开发,模板引擎是一个技术名词,是跨领域跨平台的概念,在Java语言体系下有模板引擎,在C# ...

  3. jsp页面随页面初始化加载js函数

    1 <%@ page language="java" import="java.util.*" pageEncoding="gbk"% ...

  4. 读取FTP上的excel文件,并写入数据库

    今天遇到一些问题,需要从ftp上读取一些excel文件,并需要将excel中的数据写入到数据库,这样就可以通过管理页面查看这些数据. 我将相关工作分为三步,1.从ftp上读取相关文件,并将excel文 ...

  5. Oracle 11g+Windows10 x64安装、配置过程记录

    备注:本想在自己电脑上安装个oracle练习用,但是害怕安装过程中出现问题,而oracle的卸载又是出了名的麻烦,所以用虚拟机搭建了一个跟本机一样的系统,同时记录下安装的每一步. 环境:windows ...

  6. nginx报错[error] CreateFile() "D:\Java-windows\nginx-1.16.0/logs/nginx.pid" failed (2: The system cannot find the file specified)

    无论是nginx -s stop还是nginx -s reload命令,都会出现这个错误. 解决方法:使用命令创建/logs/nginx.pid文件,命令如下所示: nginx -c conf/ngi ...

  7. Ansible自动化运维工具(2)

    (5) ping模块 检测客户端机器的连通性 ansible webserver -m ping (6) group模块 创建用户的附加组. ansible webserver -m group -a ...

  8. 封装操作mysql、redis

    封装操作mysql: import pymysql class MyDb: def __init__(self,host,password,user,db,port=3306,charset='utf ...

  9. php session之redis存储

    前提:redis已安装好. php代码: <?php ini_set("session.save_handler", "redis"); ini_set( ...

  10. Cluster基础(四):创建RHCS集群环境、创建高可用Apache服务

    一.创建RHCS集群环境 目标: 准备四台KVM虚拟机,其三台作为集群节点,一台安装luci并配置iSCSI存储服务,实现如下功能: 使用RHCS创建一个名为tarena的集群 集群中所有节点均需要挂 ...