我的c++代码规范
一、命名
类型、类、结构体、枚举类型、函数使用 PascalCase;
变量、数据成员、命名空间使用小写字母和下划线,例如 file_name;
常量使用项目统一的常量命名规则;
名称应具有明确含义,避免无意义缩写;
类成员变量应遵循统一的成员变量命名规则;
命名空间使用小写字母;
枚举值应使用具有明确语义的名称;
避免使用容易产生歧义或与已有符号冲突的名称。
二、文件与头文件
C++ 源文件使用 .cc,头文件使用 .h;
头文件必须具有防止重复包含的保护机制;
头文件应尽量自包含,不应依赖其他文件的间接 #include;
源文件应优先包含对应的头文件,以便及时发现声明与实现不一致的问题;
include 应按照统一顺序排列;
头文件应尽量减少依赖;
能够使用前置声明时,可以使用前置声明降低依赖;
头文件中不得使用 using namespace;
不应在头文件中引入不必要的实现细节。
三、格式
使用两个空格缩进;
不使用 Tab 进行缩进;
每行通常不超过 80 个字符;
大括号、空格、逗号等格式应保持统一;
运算符两侧按照统一规则保留空格;
不使用多余的空白字符;
文件末尾保留换行符;
合理使用空行划分不同逻辑部分;
不为了减少代码行数而压缩代码;
if、for、while 等控制语句使用统一的大括号风格。
四、类与函数
类应明确其职责,避免一个类承担过多无关功能;
数据成员通常不直接暴露,应通过成员函数提供访问接口;
不需要复制的类应明确禁止复制;
基类如果可能通过基类指针删除派生类对象,应使用虚析构函数;
能使用组合解决的问题,不应无必要地使用继承;
函数应保持较小的职责范围;
参数过多时应重新考虑接口设计;
不修改对象状态的成员函数应声明为 const;
不应返回局部对象的指针或引用;
不应通过返回内部对象的可修改引用破坏类的不变量。
五、类型、指针与内存管理
能使用 nullptr 时,不使用 NULL 或整数 0 表示空指针;
优先使用 RAII 管理资源;
普通对象不应通过裸 new / delete 手工管理生命周期;
动态对象优先使用智能指针;
std::unique_ptr 用于独占所有权;
std::shared_ptr 仅在确实需要共享所有权时使用,不应默认使用;
std::weak_ptr 用于需要观察对象但不参与所有权的场景;
裸指针不应隐含表达对象所有权;
引用通常用于表示一个必须存在的对象;指针可以用于表示可为空的对象;
不应返回已经失效的指针或引用;
能够声明为 const 的对象、参数和成员函数应尽量使用 const;
六、STL 与现代 C++
优先使用标准库容器、算法和工具,不重复实现已有功能;
顺序存储通常优先考虑 std::vector;
根据实际需求选择 vector、deque、list、map、set 等容器,不应仅凭习惯选择;
能使用 STL 算法时,优先使用标准算法;
使用迭代器时必须注意迭代器失效规则;
使用 auto 可以避免冗长或重复的类型声明,但如果导致类型含义不明确,应使用显式类型;
使用范围 for 简化容器遍历;
使用 nullptr 替代 NULL;
使用 constexpr 表达可以在编译期确定的值或计算;
使用移动语义减少不必要的对象复制;
优先使用类型安全的现代 C++ 特性,而不是 C 风格写法。
七、类型转换
不使用 C 风格强制类型转换;
根据实际目的使用:
static_cast:明确的、编译期可检查的类型转换;
const_cast:修改 const 属性,仅在确有必要时使用;
dynamic_cast:需要运行时类型检查时使用;
reinterpret_cast:底层类型重新解释,应尽量避免;
不应通过类型转换掩盖类型设计问题;
类型转换应尽可能靠近实际使用位置,并使转换原因清晰;
八、宏与预处理
能使用 const、constexpr、枚举、模板或函数替代的宏,不应使用宏;
不应使用宏实现复杂业务逻辑;
条件编译应仅在确有必要时使用;
宏名称应采用能够降低命名冲突的形式;
不应通过宏模拟普通 C++ 语言特性。
九、注释
注释应解释“为什么这样做”,而不是简单重复代码含义;
复杂算法应说明核心思路和必要条件;
公共接口应提供必要的说明;
注释必须与实际代码保持一致;
修改代码时应同步更新相关注释;
不应保留已经失效的注释;
TODO 应明确说明需要完成的工作;
浙公网安备 33010602011771号