Google 的 C++编程规范

1.1 头文件均使用 #define guards

#ifndef <PROJECT>_<PATH>_<FILE>_H_
#define <PROJECT>_<PATH>_<FILE>_H_...#endif  // <PROJECT>_<PATH>_<FILE>_H_

1.2 包含所有使用到的头文件

只要头文件中引用了其他文件中的符号,就需要包含该文件;(即使通过传递包含已经包含了该文件)

例如:foo.cc 应该包含 bar.h (即使 foo.h 中包含了 bar.h)

1.3 前向声明

一般使用前向声明的地方,都是使用指针(指针占用空间固定的,不用包含头文件);

但前向声明会隐藏类之间的关系(例如继承关系),这在匹配函数时就可能引发不同的行为;

1.4 内联函数不要超过10行

注意析构函数,因为隐式的成员变量和基类析构函数调用,析构函数往往比它们看起来的要长!

不要包括循环 或 switch

1.5 头文件顺序

(1)项目中的头文件应该带路径(src 目录下直到该文件的路径,不要使用 .. .

最直接关联头文件(例如在 foo.cc 文件中,此处为 foo.h,以下每类均用空行分隔)

C库

C++库

其他库

该项目其他头文件

(2)在每个模块,应该按字母顺序排序

2. 作用域

2.1 命名空间

(1)不要使用 using 语句;

不要使用 inline namespaces;(会自动把内部的标识符放到外层作用域)

在头文件之后,包含整个源文件;

(2)其名字中,字母全部小写,单词使用下划线分隔;避免缩写

Top-level namespace 应该基于项目名字;

(3)不要在头文件中使用命名空间别名,除非其作用域是局部的(例如在函数内部)

命名空间中内容不需要缩进;

2.2 匿名命名空间 (Internal Linkage)

不会被外部文件使用的变量,可以将它们放入匿名命名空间中,或声明为 static ,不要在 .h 文件中使用这两种方法;

(1)2.3 ~ 2.5 还需要进一步学习

2.3 函数和变量

(1)非成员函数尽量放到某个命名空间中;

(2)声明时就初始化变量

2.4 静态变量和全局变量

const 代表 read-only , 但这并不意味着它是不可变的,也不意味着值总是相同的。

常量随着程序的运行其值不会改变;

C++17 变量可以被声明为 inline,来保证只有一份;

2.5 线程变量

thread_local 变量实际是一些对象的集合,不同的线程实际上访问不同的对象。

在类或命名空间中必须使用编译时常量初始化;

3. 类

3.1 构造函数

构造函数中不要调用虚函数,不要抛出异常(可能失败的初始化操作);

3.2 避免隐式转换

不要定义隐式转换,必须加上 explicit 修饰单参数构造函数和转换操作符;(这将阻止 隐式转换和列表初始化语法)

3.3 拷贝/移动

一个可复制的类应该显式声明复制操作(即使使用 = default语法),一个仅移动的类应该明确声明移动操作,而一个不可复制/可移动的类则应该明确删除复制操作。

可复制的类也应该声明移动操作;

基类没有 private 部分,其可复制性/移动性由成员变量决定;
如果基类是不可复制/移动的,子类也是;

3.4 继承

尽可能使用组合关系,不得不使用继承的话,使用 public 继承;

虚函数最好都标注上 override 或 (less frequently) final

3.5 类成员变量都应该为 private,除非为常量;

3.6 命名规则

**全部小写,下划线区分单词; **

(1)类中成员变量最后有一个额外下划线;

(2)常量命名

const 或 constexpr 如果整个程序运行期间其值不变;以 k 开头;

(3)函数命名(类型名均采用这种方式 classes, structs, type aliases, enums)

每个单词首字母大写,不使用下划线

get 和 set 函数可以像变量一样命名

(4)枚举类型

enum class UrlTableError {	kOk = 0,							// 类似常量以 k 开头,每个首字母大写kOutOfMemory,kMalformedInput,
};

3.7 注释

使用 空格 而非 Tab,可以设置 IDE 一个 Tab 改为2个空格

4. 函数

4.1 参数

仅输入作用的参数放在最前面;

(1)non-optional (必须传入的参数)

input parameters 使用 值传递 或 const 引用传递;

output and input/output parameters 使用引用传递;

(2)optional (可传可不传)

input parameters : 值传递时使用 std::optional

output and input/output parameters :使用 non-const 指针;

4.2 尽量小的函数

最好不要超过 40 行,如果超过拆分成小函数;

4.3 类型转换

除非转换为 void,否则都使用 cast ;

数值类型,使用int64_t{x}

intptr_t 指针大小的整数

char 类型的空使用 ‘\0’ ;

4.4 类型推导

如果使得代码更清晰或安全,才会使用。

例如在 auto ptr = make_shared<xxx>

4.5 switch

应该总是设置 default

凡是需要顺序往下执行的(不是执行完 case 后就 break 的情况),需要添加 [[fallthrough]];

二、现代C++

1. 类型推导

1.1 模板类型推导

template<typename T>
void f(ParamType param);...f(expr);   //从expr中推导T和ParamType

基本原则:

(1)一般情况下,expr 与 T 的类型是一致的,T 一般不为引用,除非在下述第二种情况下;

(2)在模板类型推导时,有引用的实参会被视为无引用,他们的引用会被忽略

1.1.1 ParamType 是一个指针或引用,但不是通用引用

(1)ParamType 是 引用

  1. 如果 expr 的类型是一个引用,忽略引用部分
  2. 然后 expr 的类型与 ParamType 进行模式匹配来决定 T (相同的会消掉)

expr 若是指针,则仍按基本规则匹配

void f(const T& param);  这里 const 表明的是 T 本身是不可变的,若传递为 int* 指针,param 类型为  int (*const)&

(2)ParamType 是 指针,与上述类似

  1. 如果 expr 的类型是一个指针,忽略指针部分
  2. 与上述类似 。。。

expr 不能是引用;

1.1.2 ParamType 是一个通用引用
  1. 如果 expr 是左值,T 和 ParamType 都会被推导为左值引用。这非常不寻常,第一,这是模板类型推导中唯一一种T被推导为引用的情况。第二,虽然 ParamType 被声明为右值引用类型,但是最后推导的结果是左值引用。

  2. 如果 expr 是右值,就使用基本的推导规则

1.1.3 ParamType 既不是指针也不是引用

按通过传值(pass-by-value)的方式处理

  1. 如果 expr 的类型是一个引用,忽略这个引用部分;忽略 对象自身的 const/ volatile
  2. 如果 expr 的类型是一个指针,按基本规则;
1.1.4 数组和函数实参

数组和函数实参会退化为指针

void func(const char (param)[13]) ;
等价于 void func(const char *param) ;void func(const char (&param)[13]);  可以接受指向数组的引用,必须得 const char[13] 数组类型才能调用

有指向函数的引用;

template<typename T>
void f2(T & param);                 //传引用给f2
f2(someFunc);                       //param被推导为指向函数的引用,//类型是void(&)(int, double)

2. auto类型推导

(1)auto类型推导 与 模板类型推导基本一致;可将 auto 视为 T,类型说明符视为 ParamType ,等号右边值视为实参;

const auto & x  = 27; 类型说明符为 const auto &

(2)特例:使用大括号初始化的变量,auto 推导出的类型为 std::initializer_list ( 大括号里面必须是相同类型的变量),模板无法推导这种情况,除非显式写为

template<typename T>
void f(std::initializer_list<T> initList);auto a{42};  C++17 现在推导出为 int
auto a{42, 17};  C++17 中为 error
auto c = {42}; // still initializes a std::initializer_list<int>

(3)auto 可用于函数返回值或 lambda 表达式中的形参,此时其完全等价于 模板类型推导

lambda 表达式的返回值是通过 auto 规则推导。此时其完全等价于 模板类型推导

(4)lambda 中初始化捕获器中的类型推导也采用了 auto 规则,此时是真正的 auto 推导;

初始化捕获器中实际上声明了新的变量;

特列:[&] 代表引用捕获,需要注意引用变量的生命期要比 lambda 长,否则造成悬挂指针的危险;

3. decltype

尾置返回类型的好处是我们可以在函数返回类型中使用函数形参相关的信息(这种情况下不依赖 auto 推导)

decltype 应用于变量名,只是简单返回变量的声明类型;
decltype 应用于左值表达式,返回相应左值引用;
语法 decltype(auto) 表示需要推导出类型,但是它使用 decltype 的规则进行推导

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762619.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql基础01

登录 and 修改密码 登录 mysql //默认用户root ,主机名为localhost,密码为空,端口为3306 mysql -uroot -p123 -hlocalhost -p3306 //如果-p后无密码,可以通过非明文实现登录修改密码 mysqladmin -uroot -p password 123 //在root密码为空的情况下可以设置密码,否则需要旧密…

#鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行

3 月 19 日&#xff0c;#鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行。 现场&#xff0c;深圳市南山区人民政府副区长李志娜发布《2024 年南山区支持鸿蒙原生应用发展首批政策措施清单》&#xff0c;从加强鸿蒙原生应用供给能力、推动鸿蒙原生应用产业集聚、完善鸿蒙原生…

扩容分区和文件系统(Linux)

在ECS控制台上扩容云盘容量后&#xff0c;对应分区和文件系统并未扩容&#xff0c;您还需要进入ECS实例内部继续扩容云盘的分区和文件系统&#xff0c;将扩容部分的容量划分至已有分区及文件系统内&#xff0c;使云盘扩容生效。本文为您介绍如何通过两个步骤完成Linux实例云盘的…

API 接口渗透测试

1 API 接口介绍 1.1 RPC&#xff08;远程过程调用&#xff09; 远程过程调用&#xff08;英语&#xff1a;Remote Procedure Call&#xff0c;缩写为 RPC&#xff09;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序&#xff0c;而程序员无…

RecyclerView万能适配器之BaseQuickAdapter方法详解

BaseQuickAdapter方法详解 1. setNewData(List<T> data)2. addData(List<T> data)3. replaceData(int index, List<T> data) 这篇文章我们主要对BaseQuickAdapter的setNewData()、addData()、和 replaceData() 三个方法进行讲解 1. setNewData(List data) …

JavaScript高级(十三)---ES6中Set,map

ES6 Set 在ES6之前&#xff0c;我们存储数据的结构主要有两种&#xff1a;数组、对象。 在ES6中新增了另外两种数据结构&#xff1a;Set、Map&#xff0c;以及它们的另外形式WeakSet、WeakMap。 Set是一个新增的数据结构&#xff0c;可以用来保存数据&#xff0c;类似于数组&a…

应用APM-如何配置Prometheus + Grafana监控springboot应用

文章目录 概述在Spring Boot应用中集成Micrometerspringboot配置修改 Docker安装Prometheus和Grafanaprometheus配置grafana配置启动Prometheus和Grafana在Grafana中配置数据源创建Grafana仪表盘配置Grafana告警&#xff08;可选&#xff09;监控和分析 概述 配置Prometheus和…

前缀列表和route-policy

前缀列表和route-policy ACL&#xff1a;访问控制列表 1、它可以用于过滤流量报文 2、又可以过滤路由条目 前缀列表&#xff1a; 1、只能过滤路由条目 2、不能过滤流量报文 ACL&#xff1a;在过滤路由条目时&#xff0c;只能过滤路由前缀。 前缀列表&#xff1a;在过滤…

第十节HarmonyOS 常用容器组件2-Counter

1、描述 计数器组件&#xff0c;提供相应的增加或者减少的计数操作。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 2、子组件 可以包含子组件。 3、接口 Counter() 从API version 9开始…

如何在Android设备上运行深度网络

返回&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a; 下一篇&#xff1a; 介绍 在本教程中&#xff0c;您将了解如何使用 OpenCV 深度学习模块在 Android 设备上运行深度学习网络。教程是为 Android Studio 2022.2.1 编写的。…

SystemService.java 解读

frameworks/base/services/core/java/com/android/server/SystemService.java 是Android框架服务层的一个核心Java类文件&#xff0c;它在Android系统中扮演着基础服务管理的重要角色。 SystemService类通常作为系统服务的基类&#xff0c;定义了系统服务的基本结构和生命周期…

牛客小白月赛86(D剪纸游戏)

题目链接:D-剪纸游戏_牛客小白月赛86 (nowcoder.com) 题目描述: 输入描述: 输入第一行包含两个空格分隔的整数分别代表 n 和 m。 接下来输入 n行&#xff0c;每行包含 m 个字符&#xff0c;代表残缺纸张。 保证&#xff1a; 1≤n,m≤10001 字符仅有 . 和 * 两种字符&#xf…

基于ssm的实验室耗材管理系统设计与实现论文

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对实验室耗材信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性…

linux 外部GPIO Watchdog驱动适配

前言 文章描述&#xff0c; 利用外部gpio看门狗芯片驱动芯片的复位功能。 芯片&#xff1a;RK3568 平台&#xff1a; Linux ubuntu.lan 4.19.232 #27 SMP Sat Sep 23 13:43:49 CST 2023 aarch64 aarch64 aarch64 GNU/Linux 硬件接线图示 看门狗芯片采用GPIO喂狗&#xff0c;W…

蓝桥杯(3.21 刷真题)

P8682 [蓝桥杯 2019 省 B] 等差数列 import java.util.Arrays; import java.util.Scanner; public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int[] res new int[n1];for(int i1;i<n;i)res[i] sc.ne…

LeetCode540 有序数组中的单一元素

Leetcod540 有序数组中的单一元素 1.题目描述 2.解题思路 同样是二分搜索&#xff0c;利用当i为偶数时候&#xff0c;数组中单独元素左侧的所有i位置与i1位置的数字相同&#xff0c;而单独元素右侧的所有i位置与i1位置元素不同的特性&#xff0c;来进行二分搜索 3.算法思路 …

hexo怎么修改默认主题?

npm install 主题 修改_config.yml文件的theme 复制一份_config.yml 改名为_config.主题.yml hexo clean hexo g hexo s就这么简单 选主题 https://hexo.io/themes/ 比如 fluid npm install --save hexo-theme-fluid修改主题 配置新主题 执行新主题 hexo clean hexo g hexo…

K8s-网络原理-中篇

引言 本文是《深入剖析 K8s》的学习笔记&#xff0c;相关图片和案例可从https://github.com/WeiXiao-Hyy/k8s_example中获取&#xff0c;欢迎 ⭐️! 上篇主要介绍了 Flannel 插件为例&#xff0c;讲解了 K8s 里容器网络和 CNI 插件的主要工作原理。还有一种“纯三层”的网络方…

Android项目集成Flutter模块

官方文档将 Flutter module 集成到 Android 项目 按照官方文档添加Flutter模块后遇到了问题&#xff1a;Failed to apply plugin class ‘FlutterPlugin‘. 最后参考这篇文章解决了

Linux下的parted磁盘分区工具

简介 Linux下的parted分区工具是一款功能强大的磁盘分区和分区大小调整工具&#xff0c;由GNU组织开发。它支持多种分区表格式&#xff0c;包括MS-DOS&#xff08;MBR&#xff09;和GPT&#xff0c;尤其适用于规则大小超过2TB的分区&#xff0c;但也可用于小分区的规划。GPT格…