C++:代码常见规范1
头文件包含
(1)先系统头文件,后用户头文件:这是一个良好的编程习惯。系统头文件通常包含标准库的定义,而用户头文件则包含项目特定的定义。将系统头文件放在前面可以避免因用户头文件中的定义与系统头文件冲突而导致的问题。
#include <iostream> // 系统头文件
#include "myheader.h" // 用户头文件
(2)当前目录:通常不需要使用./来指定当前目录,编译器默认会在当前目录查找头文件。但如果为了明确或避免潜在的路径问题,可以使用。
#include "xxx.h" // 默认在当前目录查找
// 或
#include "./xxx.h" // 明确指定当前目录
(3)上级目录:使用…/来指定上级目录中的头文件。
#include "../xxx.h"
(4)下级目录:使用相对路径来指定下级目录中的头文件。
#include "somedir/xxx.h"
(5)平行目录:使用…/来“跳出”当前目录,然后指定平行目录。
cpp
#include "../somedir/xxx.h"
(6)只引用需要的头文件
cpp和h文件常规规则
(1) 文件名命名规则:
C++源文件(.cpp文件)和头文件(.h文件)的命名通常采用大小写混合或小写混合的方式,以便于区分和识别。例如,DiyMainview.cpp和infoview.cpp都是有效的文件名。命名时应保持一致性,以便于项目的维护和管理。
(2) 头文件保护机制:
为了避免头文件被多次包含导致的重复定义问题,通常会在头文件中使用#ifndef预处理指令来控制代码块的包含。这种机制被称为“头文件保护”或“包含卫士”。示例如下:
#ifndef ADD_H
#define ADD_H// 头文件的具体内容#endif // ADD_H 结束
其中,ADD_H是一个唯一的标识符,用于标识这个头文件。在头文件的末尾,使用#endif指令来结束这个条件编译块,并在行尾添加注释以明确指出这是头文件保护的结束。
(3) 头文件#endif注释:
为了提高代码的可读性,建议在#endif指令后添加注释,明确指出这是哪个头文件保护块的结束。这有助于在查看代码时快速理解头文件的包含关系。
(4) 头文件内容组织顺序:
为了保持头文件的结构清晰,通常建议按照以下顺序组织内容:
包含指令:首先列出其他必要的头文件包含指令。
宏定义代码块:接着定义任何需要的宏。
全局变量和常量:然后声明全局变量和常量。
类型定义:紧接着定义任何需要的类型(如结构体、联合体、枚举等)。
类定义:定义类及其成员函数和成员变量。
内联函数:最后,可以定义内联函数(如果它们与类紧密相关,也可以放在类定义内部)。
(5) 源文件(.cpp文件)内容组织顺序:
源文件的内容组织同样需要清晰明了。通常建议按照以下顺序组织:
包含指令:首先列出所有必要的头文件包含指令。
宏定义:接着定义任何需要的宏(虽然宏定义通常放在头文件中,但在源文件中也可能需要)。
全局变量:然后声明和初始化全局变量(注意,全局变量的使用应尽量避免,因为它们可能导致代码难以维护和调试)。
函数定义:最后,按照逻辑顺序定义所有函数。
注释方面
1、文件头注释
作者:记录文件的创建者或主要维护者。
文件名称:明确文件的名称,便于识别和引用。
文件说明:简要描述文件的主要功能和用途。
日期和版本(可选):记录文件的创建日期、修改日期和版本号,有助于追踪文件的变更历史。
修改和维护说明(可选):提供关于如何修改和维护文件的指南或注意事项。
2、函数注释
关键函数注释:对于实现核心逻辑或关键功能的函数,必须添加详细的注释,说明函数的用途、输入参数、输出结果和可能的副作用。
参数注释:对于特别复杂的参数或需要特别注意的参数,应说明其目的、数据类型、取值范围以及由谁负责释放内存(如果适用)。
注释位置:除了特殊情况(如内联汇编代码或特定格式的宏定义),注释应写在代码行之前,而不是之后。这有助于保持代码和注释的同步更新。
条件编译注释:对于每个#else或#endif指令,应添加行末注释以说明条件编译块的结束。这有助于理解代码的编译逻辑。
关键代码注释:对赋值操作、函数调用、复杂表达式和分支逻辑等关键代码进行注释,说明其目的和作用。这有助于其他开发者快速理解代码的逻辑。
TODO注释:对于尚未实现完整的代码或需要进一步优化的代码,应添加// TODO …注释以标记待办事项。这有助于跟踪代码的改进需求。
DEBUG注释:对于仅用于调试目的的代码(如打印调试信息或临时变量),应添加// only for DEBUG注释以提醒其他开发者在发布版本时移除这些代码。
NOTE注释:对于需要引起特别关注的代码(如潜在的错误源、性能瓶颈或设计决策),应添加// NOTE …注释以提供额外的解释或说明。
代码块结尾注释:对于较大的代码块(如for、while、do-while循环),可以在结尾处添加// end for|while|do注释以明确代码块的边界。这有助于提高代码的可读性和可维护性。但请注意,这种注释在某些情况下可能是多余的(如代码块较短或结构清晰时),因此应根据实际情况灵活使用。
命名
- 同一性
遵循基类或模块命名风格:在编写子模块或派生类时,应严格遵循其基类或整体模块的命名风格。这包括变量名、函数名、类名等的命名规则,以确保整个模块中的命名风格保持一致。 - 标识符组成
采用英文单词或其组合:标识符应采用英文单词或其组合,以确保其直观、可拼读且易于理解。用词应准确,避免使用模糊或容易混淆的词汇。
避免拼音命名:尽管拼音在某些情况下可能更方便,但为了避免潜在的误解和沟通障碍,应尽量避免使用拼音命名。 - 最小化长度与最大化信息量原则
保持标识符意思明确:在命名时,应确保标识符的意思明确且易于理解。同时,为了提高代码的可读性,应尽量缩短标识符的长度,但不应牺牲其信息量。
平衡长度与信息量:在保持标识符意思明确的前提下,通过合理的缩写和词汇选择来平衡长度与信息量。例如,可以使用“user”代替“userInformation”来表示用户信息,但前提是这种缩写在上下文中是清晰且易于理解的。 - 避免过于相似
区分大小写:尽管C++等编程语言允许大小写敏感的标识符命名,但为了避免混淆和误解,应尽量避免使用仅靠大小写区分的相似标识符。
使用不同词汇:对于具有不同含义的标识符,应使用不同的词汇来命名,以避免潜在的混淆。 - 避免重名
不同作用域中的命名:在程序中,应避免在不同级别的作用域中使用完全相同的名称来命名变量。即使它们的作用域不同而不会发生语法错误,但这种做法仍然容易导致误解和混淆。
使用命名空间:在大型项目中,可以使用命名空间来组织代码并避免命名冲突。这有助于保持代码的清晰和可维护性。 - 正确命名具有互斥意义的标识符
使用反义词组:对于具有互斥意义的标识符,应使用正确的反义词组来命名。这有助于清晰地表达它们之间的关系和差异。
保持一致性:在命名具有互斥意义的标识符时,应保持命名风格的一致性。例如,如果使用了“nMinValue”来表示最小值,则应使用“nMaxValue”来表示最大值。 - 避免名字中出现数字编号
逻辑上的编号需求:尽管在某些情况下数字编号可能是必要的(如循环变量或数组索引),但在命名时应尽量避免使用无意义的数字编号。
使用描述性词汇:为了代替数字编号,应使用更具描述性的词汇来命名变量或函数。这有助于提高代码的可读性和可维护性。
TCMR类
T类(简单数据类型类):
强调T类仅包含简单数据类型成员,且不对外部资源拥有所有权。
明确指出T类在析构过程中不会释放任何资源。
C类(从CBase继承的类):
强调C类必须从CBase(或类似基类)继承,且设计为非栈上分配对象。
建议使用智能指针或工厂模式等机制来管理C类对象的生命周期。
M类(接口类):
明确M类为纯接口类,不包含任何实现代码。
强调M类的函数命名应采用HandleXXX形式,遵循C++命名风格,避免Java风格或下划线风格。
建议M类的虚函数应设计为纯虚函数,以强制派生类实现。
R类(资源类):
指出R类通常代表系统固有资源,如文件句柄、网络连接等。
强调在开发代码中应尽量避免直接使用R类对象,而应通过封装或代理模式来管理资源。# 函数参数
(1)函数参数用a作为前缀。
(2)避免出现和匈牙利混合的命名规则如apBuffer名称。用aBuffer即可。
(3)函数参数比较多时,应考虑用结构代替。
(4)如果不能避免函数参数比较多,应在排版上可考虑每个参数占用一行,参数名竖向对齐。
函数参数
参数命名:
使用a作为函数参数的前缀,以保持一致性。
避免混合使用匈牙利命名法,如apBuffer应简化为aBuffer。
参数管理:
当函数参数较多时,考虑使用结构体或类来封装这些参数,以提高代码的可读性和可维护性。
如果无法避免多个参数,应在排版上使每个参数占用一行,并竖向对齐参数名,以增强代码的可读性。
成员变量
成员变量命名:
使用m作为成员变量的前缀。
避免混合使用匈牙利命名法,如mpBuffer应简化为mBuffer。
局部变量
循环变量和简单变量:
使用简单小写字符串命名循环变量和简单变量,如int i;。
指针变量:
使用p作为指针变量的前缀,如void* pBuffer;。
全局变量
使用g_作为全局变量的前缀,以明确标识其全局作用域。
类名
类名和对象名:
一般类和对象名应使用名词,以描述其代表的概念或实体。
成员函数名:
实现行为的类成员函数名应使用动词,以描述其行为或动作。
类的存取和查询成员函数名应使用名词或形容词,以描述其返回的属性或状态。
风格兼容性
对于移植的或开源的代码,可以沿用其原有风格,但应在项目文档中明确说明这些例外情况,以确保团队成员对代码风格有统一的认识。
在混合使用不同风格时,应尽量避免命名冲突和风格混乱,以保持代码的整体一致性和可读性。
Tab和空格
统一缩进:确保整个项目中缩进风格一致,要么全用Tab,要么全用空格,但推荐使用空格,因为空格在不同编辑器中的显示更一致。
避免多余空格:代码行结尾不应有多余空格,这可以通过代码编辑器或IDE的自动格式化功能来去除。
运算符周围空格:通常建议在运算符周围加上适当的空格以提高可读性,例如a + b而不是a+b。
类型定义中大括号
大括号位置:类、结构、枚举、联合的大括号应另起一行,这有助于提高代码的可读性和结构清晰度。
函数体大括号:函数体的大括号也应新起一行,并且{之前不应有缩进。这有助于区分函数签名和函数体。
函数
(1)函数体的{需要新起一行,在{之前不能有缩进。
(2)除了特别情况,函数体内不能出现两个空行。
(3)除了特别情况,函数体内不能宏定义指令。
(4)在一个函数体内,逻揖上密切相关的语句之间不加空行,其它地方应加空行分隔。
(5)在头文件定义的inline函数,函数之间可以不用空行,推荐用一个空行。
代码块
控制语句:if、for、while、do、try、catch等语句应自占一行,执行语句不得紧跟其后,且应始终使用大括号{},即使只有一条语句。
代码紧凑性:函数体内应避免不必要的空行,逻辑上密切相关的语句之间可以不加空行,其他地方应加空行分隔以提高可读性。
else
else风格:if语句如果有else语句,推荐使用} else {的形式编写在一行内,以保持代码的紧凑性。
代码行
单一职责:一行代码只做一件事情,这有助于提高代码的可读性和可维护性。
变量定义:多行变量定义时,为了美观可以将变量竖向对齐,但这不是强制的,取决于团队的约定。
行长度:代码行长度应控制在一定范围内(如80或120个字符),以确保在当前屏幕内可见。
switch语句
case对齐:case关键字应与switch对齐,以提高代码的可读性。
case代码块:case子语句如果有变量或复杂逻辑,应用{}包含起来。简单的case之间可以不加空行,复杂的case之间应考虑用空行分割。
default分支:为所有switch语句提供default分支,以防止未处理的情况。
break注释:如果某个case不需要break,一定要加注释声明,以避免潜在的逻辑错误。
循环
空循环:空循环可以使用for( ; ; )、while(1)或while(true),但推荐使用while(true)并加上适当的注释来说明这是一个无限循环。
类
继承:多继承中,基类应分行列出,以提高代码的可读性。单继承时,基类可以放在类定义的同一行或分行,取决于团队的约定。
虚函数重载:重载基类虚函数时,应在该组虚函数前加注释说明,例如// implement XXX。
友元声明:友元声明应放在类的末尾,以保持类的主体部分清晰。
宏
宏定义结束:宏定义通常不需要用分号结束,除非它是为了模拟函数调用。
参数括号:函数宏的每个参数都要用括号括起来,以避免宏展开时的优先级问题。
无参数宏:不带参数的宏函数也应定义成函数形式,即使它实际上不接受任何参数。
goto
避免使用goto:尽量避免使用goto语句,因为它会使代码流程变得难以理解和维护。如果确实需要使用(例如跳出多层循环),应加上适当的注释来说明其用途。
相关文章:
C++:代码常见规范1
头文件包含 (1)先系统头文件,后用户头文件:这是一个良好的编程习惯。系统头文件通常包含标准库的定义,而用户头文件则包含项目特定的定义。将系统头文件放在前面可以避免因用户头文件中的定义与系统头文件冲突而导致的问题。 #include <…...
C++(进阶五)--STL--用一颗红黑树封装map和set
目录 1.红黑树源码(简略版) 2.模板参数的控制 3.红黑树的结点 4.迭代器的实现 正向迭代器 反向迭代器 5.set的模拟实现 6.map的模拟实现 7.封装完成后的代码 RBTree.h mymap.h myset.h 1.红黑树源码(简略版) 下面我们…...
DeepSeek服务器繁忙问题的原因分析与解决方案
一、引言 随着人工智能技术的飞速发展,DeepSeek 等语言模型在众多领域得到了广泛应用。然而,在春节这段时间的使用过程中,用户常常遭遇服务器繁忙的问题,这不仅影响了用户的使用体验,也在一定程度上限制了模型的推广和…...
《手札·开源篇》数字化转型助力永磁电机企业降本增效:快速设计软件如何让研发效率提升40%?
数字化转型助力永磁电机企业降本增效:快速设计软件如何让研发效率提升40%? 一、痛点:传统研发模式正在吃掉企业的利润 永磁电机行业面临两大挑战: 研发周期长:一款新电机从设计到量产需6-12个月,电磁计算…...
飞算JavaAI :AI + 时代下的行业趋势引领者与推动者
在科技飞速发展的当下,AI 时代正以前所未有的速度重塑着各个行业的格局,而软件开发领域更是这场变革的前沿阵地。在众多创新力量之中,飞算JavaAI 脱颖而出,宛如一颗璀璨的新星,凭借其独树一帜的特性与强大功能&#x…...
【重新认识C语言----结构体篇】
目录 -----------------------------------------begin------------------------------------- 引言 1. 结构体的基本概念 1.1 为什么需要结构体? 1.2 结构体的定义 2. 结构体变量的声明与初始化 2.1 声明结构体变量 2.2 初始化结构体变量 3. 结构体成员的访…...
解决错误:CondaHTTPError: HTTP 000 CONNECTION FAILED for url
解决错误:CondaHTTPError: HTTP 000 CONNECTION FAILED for url 查看channels:vim ~/.condarcshow_channel_urls: true channels:- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/- http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/…...
使用令牌桶算法通过redis实现限流
令牌桶算法是一种常用的限流算法,它可以平滑地控制请求的处理速率。在 Java 中结合 Redis 实现令牌桶算法,可以利用 Redis 的原子操作来保证多节点环境下的限流效果。 一 实现思路 初始化令牌桶:在 Redis 中存储令牌桶的相关信息࿰…...
Docker的进程和Cgroup概念
Docker的进程和Cgroup概念 容器里的进程组织或关系0号进程:containerd-shim1号进程:容器内的第一个进程进程收到信号后的三种反应两个特权信号在容器内执行 kill 命令的行为 Cgroup 介绍CPU Cgroup 中与 CFS 相关的参数Kubernetes 中的资源管理memory cg…...
Day68:类的多态
在面向对象编程(OOP)中,多态(Polymorphism)是指不同类的对象对同一消息作出响应的能力。换句话说,多态允许不同类的对象使用相同的方法名,但实现不同的行为。多态是通过继承和方法重写来实现的,通常可以分为方法重写和接口重载。 在 Python 中,多态常常通过方法重写来…...
一种解决SoC总线功能验证完备性的技术
1. 前言 通过总线将各个IP通过总线连接起来的SoC芯片是未来的大趋势,也是缩短芯片开发周期,抢先进入市场的常用方法。如何确保各个IP是否正确连接到总线上,而且各IP的地址空间分配是否正确,是一件很棘手的事情。本文提出了一种新…...
【Linux系统】线程:线程库 / 线程栈 / 线程库源码阅读学习
一、线程库 1、线程库介绍:命名与设计 命名:线程库通常根据其实现目的和平台特性进行命名。例如,POSIX标准定义了Pthreads(POSIX Threads),这是一个广泛使用的线程库规范,适用于多种操作系统。此…...
深度剖析 Redis:缓存穿透、击穿与雪崩问题及实战解决方案
一、缓存基本使用逻辑 在应用程序中,为了提高数据访问效率,常常会使用缓存。一般的缓存使用逻辑是:根据 key 去 Redis 查询是否有数据,如果命中就直接返回缓存中的数据;如果缓存不存在,则查询数据库&#…...
如何使用el-table的多选框
对el-table再次封装,使得功能更加强大! 本人在使用el-table时,因为用到分页,导致上一页勾选的数据在再次返回时,没有选中,故在原有el-table组件的基础之上再次进行了封装。 1.首先让某些不需要勾选的列表进…...
【工具变量】上市公司企业渐进式创新程度及渐进式创新锁定数据(1991-2023年)
测算方式: 参考顶刊《经济研究》孙雅慧(2024)老师的做法,用当期创新和往期创新的内容重叠度作为衡量渐进式创新程度的合理指标。通过搜集海量专利摘要,测算当前专利申请和既有专利的内容相似度,反映企业在…...
LM Studio 部署本地大语言模型
一、下载安装 1.搜索:lm studio LM Studio - Discover, download, and run local LLMs 2.下载 3.安装 4.更改成中文 二、下载模型(软件内下载) 1.选择使用代理,否则无法下载 2.更改模型下载目录 默认下载位置 C:\Users\用户名\.lmstudio\models 3.搜…...
嵌入式工程师面试经验分享与案例解析
嵌入式工程师岗位受到众多求职者的关注。面试流程严格,技术要求全面,涵盖C/C编程、数据结构与算法、操作系统、嵌入式系统开发、硬件驱动等多个方向。本文将结合真实案例,深入剖析嵌入式工程师的面试流程、常见问题及应对策略,帮助…...
英特尔至强服务器CPU销量创14年新低,AMD取得进展
过去几年是英特尔56年历史上最艰难的时期之一。该公司在晶圆代工、消费级处理器和服务器芯片等各个领域都面临困境。随着英特尔重组其晶圆代工业务,新的分析显示其服务器业务的现状和未来前景不容乐观。 英特尔最近发布的10-K文件显示:“数据中心和人工…...
判断您的Mac当前使用的是Zsh还是Bash:echo $SHELL、echo $0
要判断您的Mac当前使用的是Zsh还是Bash,可以使用以下方法: 查看默认Shell: 打开“终端”应用程序,然后输入以下命令: echo $SHELL这将显示当前默认使用的Shell。例如,如果输出是/bin/zsh,则说明您使用的是Z…...
使用Springboot实现MQTT通信
目录 一、MQ协议 MQTT 特点 MQTT 工作原理 MQTT 主要应用场景 MQTT 配置与注意事项 二、MQTT服务器搭建 三、参考案例 MQTT(Message Queuing Telemetry Transport)是一种基于发布/订阅模型的轻量级消息传输协议,常用于物联网ÿ…...
植物大战僵尸融合版(电脑/安卓)
《植物大战僵尸融合版》是一款由B站UP主“蓝飘飘fly”制作的同人策略塔防游戏,基于经典《植物大战僵尸》玩法,加入了独特的植物融合系统。 出于方便,软件是便携版,解压后双击即可畅玩。 游戏主页依旧是植物大战僵尸经典界面。右下…...
02DevOps基础环境准备
准备两台Linux的操作系统,最简单的方式就是在本机上使用虚拟机搭建两个操作系统(实际生产环境是两台服务器,虚拟机的方式用于学习使用) 我搭建的两台服务器的ip分别是192.168.1.10、192.168.1.11 192.168.1.10服务器用于安装doc…...
苍穹外卖-day12(工作台、数据导出)
工作台Apache POI导出运营数据Excel报表 功能实现:工作台、数据导出 工作台效果图: 数据导出效果图: 在数据统计页面点击数据导出:生成Excel报表 1. 工作台 1.1 需求分析和设计 1.1.1 产品原型 工作台是系统运营的数据看板&…...
说一下 Tcp 粘包是怎么产生的?
TCP 粘包是什么? TCP 粘包(TCP Packet Merging) 是指多个小的数据包在 TCP 传输过程中被合并在一起,接收方读取时无法正确分辨数据边界,导致数据解析错误。 TCP 是流式协议,没有数据包的概念,…...
详解享元模式
引言 在计算机中,内存是非常宝贵的资源,而程序中可能会有大量相似或相同的对象,它们的存在浪费了许多空间。而享元模式通过共享这些对象,从而解决这种问题的。 1.概念 享元模式(Flyweight Pattern):运用共享技术有效地…...
第18章 不可变对象设计模式(Java高并发编程详解:多线程与系统设计)
1.线程安全 所谓共享的资源,是指在多个线程同时对其进行访问的情况下,各线程都会使其发生变化,而线程安全性的主要目的就在于在受控的并发访问中防止数据发生变化。除了使用synchronized关键字同步对资源的写操作之外, 还可以在线…...
openEuler22.03LTS系统升级docker至26.1.4以支持启用ip6tables功能
本文记录了openEuler22.03LTS将docker升级由18.09.0升级至26.1.4的过程(当前docker最新版本为27.5.1,生产环境为保障稳定性,选择升级到上一个大版本26的最新小版本)。 一、现有环境 1、系统版本 [rootlocalhost opt]# cat /etc…...
< OS 有关 > Ubuntu 版本升级 实践 24.04 -> 24.10, 安装 .NET
原因: 想安装 .NET 9 去编译 GitHut 项目,这回用不熟悉的 Ubuntu来做,不知道怎么拐去给 Ubuntu 升级,看到现在版本是 24.10 但不是 LTS 版本,记录下升级过程。 一、实践过程: 1. 查看当前版本 命令1: l…...
某咨询大数据解决方案介绍(32页PPT)
本文档介绍了一个大数据平台解决方案,旨在解决企业当前面临的数据问题,包括数据定义缺失、重复采集和存储、数据不完整以及缺乏可靠决策依据等。通过引入大数据技术,该方案强调从被动的IT支撑向主动的数据核心服务转型,以实现科学…...
ZooKeeper作为注册中心有什么问题? ZooKeeper作为注册中心,海量服务同时重启有什么问题?
目录 ZooKeeper作为注册中心存在的问题 性能瓶颈 一致性保证 复杂性 扩展性 单点故障 数据模型限制 社区和生态 安全性 总结 ZooKeeper作为注册中心,海量服务同时重启有的问题 1. ZooKeeper集群压力剧增 2. ZooKeeper Leader节点压力 3. 会话和临时节点管理 4.…...
