AUTOSAR C++ 2014 规范
AUTOSAR Cpp 2014 规范
https://ww2.mathworks.cn/help/bugfinder/autosar-c-14.html?lang=en
语言无关性问题
[规则 A0-1-1] 项目中不得出现为非易失性变量赋值后,该值后续未被使用的情况。
[规则 A0-1-2] 非重载运算符、且返回类型非 void 的函数,其返回值必须被使用。
[规则 A0-1-3] 匿名命名空间中定义的所有函数、具有内部链接性的静态函数、私有成员函数,都必须被使用。
[规则 A0-1-4] 非虚函数中不得存在未使用的命名参数。
[规则 A0-1-5] 虚函数及其所有重写函数的参数集合中,不得存在未使用的命名参数。
[规则 A0-1-6] 不应存在未使用的类型声明。
[规则 A0-4-2] 不得使用 long double 类型。
[规则 A0-4-4] 使用数学函数时,必须对范围错误、定义域错误和极点错误进行检查。
[规则 M0-1-1] 项目中不得存在不可达代码。
[规则 M0-1-2] 项目中不得存在不可执行路径。
[规则 M0-1-3] 项目中不得存在未使用的变量。
[规则 M0-1-4] 项目中不得存在仅被使用一次的非易失性 POD 变量。
[规则 M0-1-8] 所有返回类型为 void 的函数,必须具备外部副作用。
[规则 M0-1-9] 不得存在死代码。
[规则 M0-1-10] 每个已定义的函数都应至少被调用一次。
[规则 M0-2-1] 不得将对象赋值给内存重叠的对象。
[规则 M0-3-2] 若函数会生成错误信息,则必须对该错误信息进行检测。
通用原则
[规则 A1-1-1] 所有代码必须符合《ISO/IEC 14882:2014 C++ 编程语言》标准,且不得使用已弃用的特性。
词法约定
[规则 A2-3-1] 源代码中只能使用 C++ 语言标准基础源字符集中规定的字符。
[规则 A2-5-1] 不得使用三字符组。
[规则 A2-5-2] 不得使用双字符组。
[规则 A2-7-1] 反斜杠 \ 不得出现在 C++ 注释的末尾。
[规则 A2-7-2] 不得通过 “注释掉” 的方式屏蔽代码段。
[规则 A2-7-3] 所有 “用户自定义” 类型、静态与非静态数据成员、函数及方法的声明前,必须附带文档说明。
[规则 A2-8-1] 头文件名应能体现其声明内容对应的逻辑实体。
[规则 A2-8-2] 实现文件名应能体现其定义内容对应的逻辑实体。
[规则 A2-10-1] 内层作用域中声明的标识符,不得隐藏外层作用域中声明的标识符。
[规则 A2-10-4] 具有静态存储期的非成员对象或静态函数的标识符名称,不得在同一命名空间内重复使用。
[规则 A2-10-5] 具有静态存储期的函数、具有外部或内部链接性的非成员对象的标识符名称,不应重复使用。
[规则 A2-10-6] 类或枚举名称,不得被同一作用域中的变量、函数或枚举常量声明所隐藏。
[规则 A2-11-1] 不得使用 volatile 关键字。
[规则 A2-13-1] 只能使用 ISO/IEC 14882:2014 标准中定义的转义序列。
[规则 A2-13-2] 不得拼接具有不同编码前缀的字符串字面量。
[规则 A2-13-3] 不得使用 wchar_t 类型。
[规则 A2-13-4] 不得将字符串字面量赋值给非 const 指针。
[规则 A2-13-5] 十六进制常量应使用大写形式。
[规则 A2-13-6] 通用字符名只能在字符或字符串字面量内部使用。
[规则 M2-7-1] C 风格注释中不得出现 /* 字符序列。
[规则 M2-10-1] 不同的标识符在排版上必须无歧义。
[规则 M2-13-2] 不得使用零以外的八进制常量,以及 \0 以外的八进制转义序列。
[规则 M2-13-3] 所有无符号类型的八进制或十六进制整数字面量,都必须添加 U 后缀。
[规则 M2-13-4] 字面量后缀必须使用大写形式。
基础概念
[规则 A3-1-1] 所有头文件必须支持在多个翻译单元中引入,且不违反单一定义规则(ODR)。
[规则 A3-1-2] 项目中本地定义的头文件,文件扩展名必须为 .h、.hpp 或 .hxx 其中之一。
[规则 A3-1-3] 项目中本地定义的实现文件,文件扩展名应为 .cpp。
[规则 A3-1-4] 声明具有外部链接性的数组时,必须显式指定其大小。
[规则 A3-1-5] 函数定义仅在满足以下任一条件时,才能放置在类定义内部:(1) 函数需要被内联;(2) 是成员函数模板;(3) 是类模板的成员函数。
[规则 A3-1-6] 简单的读取和修改器函数应被内联。
[规则 A3-3-1] 具有外部链接性的对象或函数(包括具名命名空间的成员),必须在头文件中声明。
[规则 A3-3-2] 静态对象和线程局部对象必须进行常量初始化。
[规则 A3-8-1] 不得在对象的生命周期之外访问该对象。
[规则 A3-9-1] 必须使用 <cstdint> 头文件中定义的、明确指明大小和符号性的定宽整数类型,替代基础数值类型。
[规则 M3-1-2] 不得在块作用域中声明函数。
[规则 M3-2-1] 同一对象或函数的所有声明,必须具有兼容的类型。
[规则 M3-2-2] 不得违反单一定义规则。
[规则 M3-2-3] 在多个翻译单元中使用的类型、对象或函数,必须且只能在一个文件中声明。
[规则 M3-2-4] 具有外部链接性的标识符,必须有且仅有一个定义。
[规则 M3-3-2] 若函数具有内部链接性,则其所有重声明都必须包含 static 存储类说明符。
[规则 M3-4-1] 声明为对象或类型的标识符,必须在能最小化其可见性的块中定义。
[规则 M3-9-1] 对象类型、函数返回类型、函数参数所使用的类型,在所有声明和重声明中,必须逐标记完全一致。
[规则 M3-9-3] 不得使用浮点值的底层二进制位表示。
标准约定
[规则 A4-5-1] enum 或 enum class 类型的表达式,不得作为以下运算符之外的内置及重载运算符的操作数:下标运算符 []、赋值运算符 =、相等运算符 == 与 !=、取地址运算符 &、关系运算符 <、<=、>、>=。
[规则 A4-7-1] 整数表达式不得导致数据丢失。
[规则 A4-10-1] 只能使用 nullptr 字面量作为空指针常量。
[规则 M4-5-1] bool 类型的表达式,不得作为以下运算符之外的内置运算符的操作数:赋值运算符 =、逻辑运算符 &&、||、!、相等运算符 == 与 !=、取地址运算符 &、条件运算符。
[规则 M4-5-3] 普通 char 类型与 wchar_t 类型的表达式,不得作为以下运算符之外的内置运算符的操作数:赋值运算符 =、相等运算符 == 与 !=、取地址运算符 &。
[规则 M4-10-1] 不得将 NULL 用作整数值。
[规则 M4-10-2] 不得将字面量零 (0) 用作空指针常量。
表达式
[规则 A5-0-1] 表达式的求值结果,在标准允许的任意求值顺序下必须保持一致。
[规则 A5-0-2] if 语句的条件与循环语句的条件,必须为 bool 类型。
[规则 A5-0-3] 对象声明中,指针的间接寻址层级不得超过两层。
[规则 A5-0-4] 指针算术运算不得作用于指向非 final 类的指针。
[规则 A5-1-1] 除类型初始化外,不得直接使用字面量值,应使用符号名称替代。
[规则 A5-1-2] lambda 表达式中不得隐式捕获变量。
[规则 A5-1-3] 每个 lambda 表达式都必须包含参数列表(可为空)。
[规则 A5-1-4] lambda 表达式对象的生命周期,不得超过其任何按引用捕获的对象的生命周期。
[规则 A5-1-6] 返回类型非 void 的 lambda 表达式,应显式指定返回类型。
[规则 A5-1-7] lambda 不得作为 decltype 或 typeid 的操作数。
[规则 A5-1-8] 不应在另一个 lambda 表达式内部定义 lambda 表达式。
[规则 A5-1-9] 相同的匿名 lambda 表达式,应替换为具名函数或具名 lambda 表达式。
[规则 A5-2-1] 不应使用 dynamic_cast。
[规则 A5-2-2] 不得使用传统的 C 风格强制类型转换。
[规则 A5-2-3] 强制类型转换不得移除指针或引用类型的 const 或 volatile 限定。
[规则 A5-2-4] 不得使用 reinterpret_cast。
[规则 A5-2-5] 不得越界访问数组或容器。
[规则 A5-2-6] 逻辑与 &&、逻辑或 || 的操作数若包含二元运算符,必须为操作数添加括号。
[规则 A5-3-1] typeid 运算符的操作数求值过程,不得产生副作用。
[规则 A5-3-2] 不得解引用空指针。
[规则 A5-3-3] 不得删除指向不完整类类型的指针。
[规则 A5-5-1] 指向成员的指针,不得访问类中不存在的成员。
[规则 A5-6-1] 整数除法或取余运算符的右操作数不得为零。
[规则 A5-10-1] 指向虚成员函数的成员指针,仅能与空指针常量进行相等性判断。
[规则 A5-16-1] 三元条件运算符不得作为子表达式使用。
[规则 M5-0-2] 表达式中应尽量减少对 C++ 运算符优先级规则的依赖。
[规则 M5-0-3] 左值表达式不得被隐式转换为不同的底层类型。
[规则 M5-0-4] 隐式整数转换不得改变底层类型的符号性。
[规则 M5-0-5] 不得进行浮点与整数类型之间的隐式转换。
[规则 M5-0-6] 隐式整数或浮点转换不得缩减底层类型的大小。
[规则 M5-0-7] 不得对左值表达式进行浮点与整数类型之间的显式转换。
[规则 M5-0-8] 显式整数或浮点转换不得扩大左值表达式底层类型的大小。
[规则 M5-0-9] 显式整数转换不得改变左值表达式底层类型的符号性。
[规则 M5-0-10] 若按位取反 ~ 和左移 << 运算符作用于底层类型为 unsigned char 或 unsigned short 的操作数,其结果必须立即转换回操作数的底层类型。
[规则 M5-0-11] 普通 char 类型仅可用于字符值的存储与使用。
[规则 M5-0-12] signed char 与 unsigned char 类型仅可用于数值的存储与使用。
[规则 M5-0-14] 条件运算符的第一个操作数必须为 bool 类型。
[规则 M5-0-15] 数组下标是唯一允许使用的指针算术运算形式。
[规则 M5-0-16] 指针算术运算中的原始指针操作数,以及运算生成的结果指针,都必须指向同一数组的元素。
[规则 M5-0-17] 指针之间的减法运算,仅能作用于指向同一数组元素的指针。
[规则 M5-0-18] 除指向同一数组的情况外,>、>=、<、<= 运算符不得作用于指针对象。
[规则 M5-0-20] 二元位运算符的非常量操作数,必须具有相同的底层类型。
[规则 M5-0-21] 位运算符仅能作用于无符号底层类型的操作数。
[规则 M5-2-2] 指向虚基类的指针,仅能通过 dynamic_cast 转换为指向派生类的指针。
[规则 M5-2-3] 多态类型不应执行从基类到派生类的强制类型转换。
[规则 M5-2-6] 不得将函数指针转换为任何其他指针类型,包括其他函数指针类型。
[规则 M5-2-8] 不得将整数类型对象或 void 类型指针转换为指针类型对象。
[规则 M5-2-9] 不得将指针类型转换为整数类型。
[规则 M5-2-10] 自增 (++) 和自减 (--) 运算符不得与表达式中的其他运算符混用。
[规则 M5-2-11] 不得重载逗号运算符、&& 运算符和 || 运算符。
[规则 M5-2-12] 作为函数参数传递的数组类型标识符,不得退化为指针。
[规则 M5-3-1] 逻辑非 ! 运算符、逻辑与 &&、逻辑或 || 运算符的每个操作数,都必须为 bool 类型。
[规则 M5-3-2] 一元负号运算符不得作用于底层类型为无符号的表达式。
[规则 M5-3-3] 不得重载取地址 & 运算符。
[规则 M5-3-4] sizeof 运算符的操作数求值过程,不得产生副作用。
[规则 M5-8-1] 移位运算符的右操作数,必须大于等于 0,且小于左操作数底层类型的位宽。
[规则 M5-14-1] 逻辑与 &&、逻辑或 || 运算符的右操作数,不得产生副作用。
[规则 M5-18-1] 不得使用逗号运算符。
[规则 M5-19-1] 无符号整数常量表达式的求值不得发生回绕。
语句
[规则 A6-2-1] 移动与拷贝赋值运算符,必须仅对类的基类和数据成员执行对应的移动或拷贝操作,不得产生任何额外副作用。
[规则 A6-2-2] 表达式语句不得仅为临时对象构造函数的显式调用。
[规则 A6-4-1] switch 语句必须包含至少两个与 default 标签不同的 case 分支。
[规则 A6-5-1] 若 for 循环遍历容器的所有元素,且未使用循环计数器,则不得使用该 for 循环。
[规则 A6-5-2] for 循环必须包含唯一的循环计数器,且循环计数器不得为浮点类型。
[规则 A6-5-3] 不应使用 do-while 语句。
[规则 A6-5-4] for 循环的初始化语句和循环表达式,不得执行循环计数器初始化与修改之外的操作。
[规则 A6-6-1] 不得使用 goto 语句。
[规则 M6-2-1] 赋值运算符不得在子表达式中使用。
[规则 M6-2-2] 不得直接或间接对浮点表达式进行相等或不等判断。
[规则 M6-2-3] 预处理前,空语句必须单独占一行;其后可跟随注释,但空语句后的第一个字符必须为空白字符。
[规则 M6-3-1] switch、while、do-while 或 for 语句的循环体语句,必须为复合语句。
[规则 M6-4-1] if (条件) 结构后必须跟随复合语句;else 关键字后必须跟随复合语句或另一个 if 语句。
[规则 M6-4-2] 所有 if...else if 结构必须以 else 子句结尾。
[规则 M6-4-3] switch 语句必须是格式良好的 switch 语句。
[规则 M6-4-4] switch 标签仅能在最内层闭合的复合语句为 switch 语句体时使用。
[规则 M6-4-5] 每个非空的 switch 分支,必须以无条件的 throw 或 break 语句终止。
[规则 M6-4-6] switch 语句的最后一个分支必须是 default 分支。
[规则 M6-4-7] switch 语句的条件不得为 bool 类型。
[规则 M6-5-2] 若循环计数器未通过 -- 或 ++ 修改,则在循环条件中,循环计数器仅能作为 <=、<、>、>= 运算符的操作数。
[规则 M6-5-3] 不得在循环条件或循环体中修改循环计数器。
[规则 M6-5-4] 循环计数器仅能通过以下操作修改:--、++、-=n 或 +=n;其中 n 在循环执行期间必须保持恒定。
[规则 M6-5-5] 循环控制变量中,除循环计数器外的其他变量,不得在循环条件或循环表达式中修改。
[规则 M6-5-6] 循环控制变量中,除循环计数器外、在循环体中被修改的变量,必须为 bool 类型。
[规则 M6-6-1] goto 语句引用的任何标签,必须在同一代码块中,或在包含该 goto 语句的代码块中声明。
[规则 M6-6-2] goto 语句必须跳转到同一函数体中、声明在其后方的标签。
[规则 M6-6-3] continue 语句仅能在格式良好的 for 循环中使用。
声明
[规则 A7-1-1] 不可变数据的声明必须使用 constexpr 或 const 说明符。
[规则 A7-1-2] 编译期可确定的值,必须使用 constexpr 说明符。
[规则 A7-1-3] CV 限定符必须放置在 typedef 或 using 定义的类型名称的右侧。
[规则 A7-1-4] 不得使用 register 关键字。
[规则 A7-1-5] auto 说明符仅能在以下场景中使用:(1) 声明变量的类型与函数调用的返回类型一致;(2) 声明变量的类型与非基础类型的初始化值类型一致;(3) 声明泛型 lambda 表达式的参数;(4) 使用尾置返回类型语法声明函数模板。
[规则 A7-1-6] 不得使用 typedef 说明符。
[规则 A7-1-7] 每个表达式语句和标识符声明,必须单独占一行。
[规则 A7-1-8] 声明中,非类型说明符必须放置在类型说明符之前。
[规则 A7-1-9] 类、结构体或枚举不得在其类型定义中声明。
[规则 A7-2-1] 枚举底层类型的表达式,其值只能对应枚举的枚举常量。
[规则 A7-2-2] 必须显式定义枚举的底层类型。
[规则 A7-2-3] 枚举必须声明为带作用域的枚举类(enum class)。
[规则 A7-2-4] 枚举中,必须满足以下三种情况之一:(1) 所有枚举常量都不初始化;(2) 仅第一个枚举常量初始化;(3) 所有枚举常量都初始化。
[规则 A7-3-1] 函数的所有重载版本,在调用处必须可见。
[规则 A7-5-1] 函数不得返回指向 const 引用传递的参数的引用或指针。
[规则 A7-5-2] 函数不得直接或间接调用自身。
[规则 A7-6-1] 声明了 [[noreturn]] 属性的函数不得返回。
[规则 M7-1-2] 函数中的指针或引用类型参数,若对应的对象在函数内不会被修改,必须声明为指向 const 的指针或 const 引用。
[规则 M7-3-1] 全局命名空间中只能包含 main 函数、命名空间声明和 extern "C" 声明。
[规则 M7-3-2] main 标识符不得用于全局 main 函数之外的其他函数。
[规则 M7-3-3] 头文件中不得出现匿名命名空间。
[规则 M7-3-4] 不得使用 using 指令(using-directives)。
[规则 M7-3-6] 头文件中不得使用 using 指令和 using 声明(类作用域或函数作用域内的 using 声明除外)。
[规则 A7-4-1] 不得使用 asm 声明。
[规则 M7-4-2] 汇编指令只能通过 asm 声明引入。
[规则 M7-4-3] 汇编代码必须进行封装与隔离。
[规则 M7-5-1] 函数不得返回指向其内部定义的自动变量(包括参数)的引用或指针。
[规则 M7-5-2] 自动存储期对象的地址,不得赋值给在该对象销毁后仍可能存在的其他对象。
声明符
[规则 A8-2-1] 声明函数模板时,若返回类型依赖于参数类型,必须使用尾置返回类型语法。
[规则 A8-4-1] 不得使用省略号语法定义函数。
[规则 A8-4-2] 返回类型非 void 的函数,其所有退出路径都必须带有表达式的显式 return 语句。
[规则 A8-4-3] 应使用通用的参数传递方式。
[规则 A8-4-4] 函数的多个返回值应通过结构体或元组返回。
[规则 A8-4-5] 声明为 X && 的 “消费型” 参数,必须始终对其执行移动操作。
[规则 A8-4-6] 声明为 T && 的 “转发型” 参数,必须始终对其执行完美转发。
[规则 A8-4-7] “入参” 类型若拷贝成本低,应按值传递。
[规则 A8-4-8] 不得使用输出型参数。
[规则 A8-4-9] 声明为 T & 的 “入出型” 参数,在函数内必须被修改。
[规则 A8-4-10] 若参数不可为 NULL,必须按引用传递。
[规则 A8-4-11] 智能指针仅在需要表达生命周期语义时,才能作为参数类型使用。
[规则 A8-4-12] std::unique_ptr 传递给函数时,仅能采用以下两种形式:(1) 按值拷贝,表达函数接管所有权;(2) 左值引用,表达函数会替换其管理的对象。
[规则 A8-4-13] std::shared_ptr 传递给函数时,仅能采用以下三种形式:(1) 按值拷贝,表达函数共享所有权;(2) 左值引用,表达函数会替换其管理的对象;(3) const 左值引用,表达函数会保留其引用计数。
[规则 A8-4-14] 接口必须具备精确的强类型定义。
[规则 A8-5-0] 所有内存必须在读取前完成初始化。
[规则 A8-5-1] 初始化列表必须遵循以下初始化顺序:(1) 按继承图的深度优先、从左到右顺序初始化虚基类;(2) 按继承列表从左到右顺序初始化直接基类;(3) 按类定义中的声明顺序初始化非静态数据成员。
[规则 A8-5-2] 变量初始化必须使用不带等号的大括号列表初始化 {}。
[规则 A8-5-4] 若类的用户声明构造函数包含 std::initializer_list 类型的参数,则该类除特殊成员函数外,只能拥有这一个构造函数。
[规则 A8-5-3] auto 类型的变量不得使用 {} 或 ={} 的大括号初始化方式。
[规则 M8-0-1] 一个初始化声明符列表或成员声明符列表,必须仅包含一个初始化声明符或成员声明符。
[规则 M8-3-1] 重写的虚函数中的参数,要么使用与被重写函数完全相同的默认实参,要么不指定任何默认实参。
[规则 M8-4-2] 函数重声明中使用的参数标识符,必须与声明中的标识符完全一致。
[规则 M8-4-4] 函数标识符要么用于调用函数,要么必须在其前添加 & 运算符。
[规则 M8-5-2] 数组和结构体的非零初始化,必须使用大括号来标识和匹配结构。
类
[规则 A9-3-1] 成员函数不得返回指向类所拥有的私有或受保护数据的非 const 原始指针或引用。
[规则 A9-5-1] 不得使用联合体 Union。
[规则 A9-6-1] 用于硬件交互或符合通信协议的数据类型,必须是平凡、标准布局类型,且仅包含大小明确的类型成员。
[规则 M9-3-1] const 成员函数不得返回指向类数据的非 const 指针或引用。
[规则 M9-3-3] 成员函数若能声明为 static,必须声明为 static;否则若能声明为 const,必须声明为 const。
[规则 M9-6-4] 有符号整数类型的具名位域,其位宽必须大于 1。
派生类
[规则 A10-1-1] 一个类的非接口类基类不得超过一个。
[规则 A10-2-1] 非虚的公有或受保护成员函数,不得在派生类中重定义。
[规则 A10-3-1] 虚函数声明必须且只能包含以下三个说明符中的一个:(1) virtual;(2) override;(3) final。
[规则 A10-3-2] 每个重写的虚函数都必须使用 override 或 final 说明符声明。
[规则 A10-3-3] 最终类中不得引入虚函数。
[规则 A10-3-5] 用户自定义的赋值运算符不得为虚函数。
[规则 A10-4-1] 类继承体系应基于接口类构建。
[规则 M10-1-1] 类不应从虚基类派生。
[规则 M10-1-2] 基类仅在钻石型继承体系中使用时,才能声明为虚基类。
[规则 M10-1-3] 可访问的基类,不得在同一继承体系中同时作为虚基类和非虚基类存在。
[规则 M10-2-1] 多继承体系中所有可访问的实体名称必须唯一。
[规则 M10-3-3] 仅当虚函数本身声明为纯虚函数时,才能被纯虚函数重写。
成员访问控制
[规则 A11-0-1] 非 POD 类型应定义为 class。
[规则 A11-0-2] 定义为 struct 的类型必须满足以下全部要求:(1) 仅提供公有数据成员;(2) 不提供任何特殊成员函数或方法;(3) 不能作为其他结构体或类的基类;(4) 不能从其他结构体或类继承。
[规则 A11-3-1] 不得使用友元声明。
[规则 M11-0-1] 非 POD 类类型的成员数据必须为私有。
特殊成员函数
[规则 A12-0-1] 若类通过 “=default"、"=delete” 或用户自定义声明,声明了拷贝操作、移动操作或析构函数中的任意一个,则必须同时声明这五个特殊成员函数中的其余所有函数。
[规则 A12-0-2] 不得对对象执行按位操作,以及假设对象内存数据布局的操作。
[规则 A12-1-1] 构造函数必须显式初始化所有虚基类、所有直接非虚基类以及所有非静态数据成员。
[规则 A12-1-2] 同一类型中,不得同时使用非静态数据成员初始化(NSDMI)和构造函数中的非静态成员初始化器。
[规则 A12-1-3] 若类的所有用户自定义构造函数,都为数据成员初始化了跨所有构造函数一致的常量值,则必须改用 NSDMI 初始化该数据成员。
[规则 A12-1-4] 所有可通过单个基础类型参数调用的构造函数,必须声明为 explicit。
[规则 A12-1-5] 类的非常量成员的通用初始化,必须通过委托构造函数实现。
[规则 A12-1-6] 无需额外显式初始化、且需要使用基类所有构造函数的派生类,必须使用继承构造函数。
[规则 A12-4-1] 基类的析构函数必须是公有的虚函数、公有的重写虚函数,或受保护的非虚函数。
[规则 A12-4-2] 若类的公有析构函数为非虚函数,则该类应声明为 final。
[规则 A12-6-1] 构造函数初始化的所有类数据成员,必须使用成员初始化器完成初始化。
[规则 A12-7-1] 若用户自定义的特殊成员函数的行为,与编译器隐式定义的特殊成员函数完全一致,则必须使用 “=default” 定义,或不进行显式定义。
[规则 A12-8-1] 移动与拷贝构造函数,必须仅对类的基类和数据成员执行对应的移动或拷贝操作,不得产生任何额外副作用。
[规则 A12-8-2] 用户自定义的拷贝与移动赋值运算符,应使用用户自定义的无异常 swap 函数实现。
[规则 A12-8-3] 不得对已移动的对象进行读访问。
[规则 A12-8-4] 移动构造函数不得使用拷贝语义初始化其类成员和基类。
[规则 A12-8-5] 拷贝赋值运算符与移动赋值运算符必须能够处理自赋值场景。
[规则 A12-8-6] 基类中的拷贝和移动构造函数、拷贝和移动赋值运算符,必须声明为受保护的,或使用 “=delete” 定义。
[规则 A12-8-7] 赋值运算符应使用 & 左值引用限定符声明。
[规则 M12-1-1] 不得在构造函数或析构函数体内,使用对象的动态类型。
重载
[规则 A13-1-2] 用户自定义字面量运算符的自定义后缀,必须以下划线开头,后接一个及以上字母。
[规则 A13-1-3] 用户自定义字面量运算符,只能对传入的参数执行转换操作。
[规则 A13-2-1] 赋值运算符必须返回指向 this 的引用。
[规则 A13-2-2] 二元算术运算符和位运算符必须返回纯右值(prvalue)。
[规则 A13-2-3] 关系运算符必须返回布尔值。
[规则 A13-3-1] 以转发引用作为参数的函数,不得进行重载。
[规则 A13-5-1] 若重载了非 const 版本的 operator[],必须同时实现 const 版本。
[规则 A13-5-2] 所有用户自定义转换运算符必须声明为 explicit。
[规则 A13-5-3] 不应使用用户自定义转换运算符。
[规则 A13-5-4] 若定义了一对互逆的运算符,其中一个必须基于另一个实现。
[规则 A13-5-5] 比较运算符必须为非成员函数,且具有相同的参数类型与 noexcept 说明。
[规则 A13-6-1] 数字分隔符 ' 仅能在以下场景使用:(1) 十进制数,每 3 位数字使用一个;(2) 十六进制数,每 2 位数字使用一个;(3) 二进制数,每 4 位数字使用一个。
模板
[规则 A14-1-1] 模板必须对传入的模板实参是否适配该模板进行检查。
[规则 A14-5-1] 模板构造函数不得参与针对所属类类型单个参数的重载决议。
[规则 A14-5-2] 不依赖于模板类参数的类成员,必须在单独的基类中定义。
[规则 A14-5-3] 非成员泛型运算符,只能在不包含类(结构体)类型、枚举类型或联合体类型声明的命名空间中声明。
[规则 A14-7-1] 作为模板实参的类型,必须提供模板所使用的所有成员。
[规则 A14-7-2] 模板特化必须在以下同一文件中声明:(1) 主模板所在文件;(2) 该特化对应的用户自定义类型所在文件。
[规则 A14-8-2] 不得使用函数模板的显式特化。
[规则 M14-5-3] 若类中存在以泛型参数为参数的模板赋值运算符,必须同时声明拷贝赋值运算符。
[规则 M14-6-1] 拥有依赖基类的类模板中,所有可能在该依赖基类中找到的名称,必须通过限定 id 或 this-> 的方式引用。
异常处理
[规则 A15-0-2] 所有操作必须至少提供异常安全的基本保证。此外,每个函数可选择提供强保证或无异常保证。
[规则 A15-0-3] 必须考虑被调用函数的异常安全保证。
[规则 A15-0-7] 异常处理机制必须保证最坏情况下的执行时间是可确定的。
[规则 A15-1-1] 只应抛出派生自 std::exception 的类型实例。
[规则 A15-1-2] 异常对象不得为指针类型。
[规则 A15-1-3] 所有抛出的异常应具备唯一性。
[规则 A15-1-4] 若函数因异常退出,则在抛出异常前,必须将函数内构造的所有对象或资源置于有效状态,或对其进行销毁。
[规则 A15-1-5] 不得跨执行边界抛出异常。
[规则 A15-2-1] 非 noexcept 的构造函数,不得在程序启动前被调用。
[规则 A15-2-2] 若构造函数为非 noexcept,且无法完成对象初始化,则必须释放该对象的资源并抛出异常。
[规则 A15-3-3] main 函数与任务主函数,必须至少捕获以下异常:所使用的所有第三方库的基类异常、std::exception,以及其他所有未处理的异常。
[规则 A15-3-4] 全捕获处理(省略号 ... 与 std::exception)仅能在以下场景使用:(a) main 函数;(b) 任务主函数;(c) 用于隔离独立组件的函数;(d) 调用使用不符合 AUTOSAR C++14 指南的异常的第三方代码时。。
[规则 A15-3-5] 类类型异常必须通过引用或 const 引用捕获。
[规则 A15-4-1] 不得使用动态异常说明。
[规则 A15-4-2] 声明为 noexcept、noexcept(true) 或 noexcept(<true condition>) 的函数,不得因异常退出。
[规则 A15-4-3] 函数的 noexcept 说明,在所有翻译单元中必须完全一致;对于虚成员函数与其重写函数,重写函数的 noexcept 说明必须与基类一致,或限制更严格。
[规则 A15-4-4] 无异常抛出的函数声明,必须包含 noexcept 说明符。
[规则 A15-4-5] 函数可能抛出的受检异常,必须与函数声明一同指定,且在该函数的所有声明及所有重写函数中必须完全一致。
[规则 A15-5-1] 所有用户自定义的类析构函数、内存释放函数、移动构造函数、移动赋值运算符和 swap 函数,不得因异常退出。应根据需要为这些函数添加 noexcept 异常说明。
[规则 A15-5-2] 程序不得被异常终止。尤其不得隐式或显式调用 std::abort()、std::quick_exit()、std::_Exit()、std::terminate()。
[规则 A15-5-3] 不得隐式调用 std::terminate() 函数。
[规则 M15-0-3] 不得使用 goto 或 switch 语句将控制流转移到 try 或 catch 代码块内部。
[规则 M15-1-1] throw 语句的赋值表达式本身,不得导致异常抛出。
[规则 M15-1-2] 不得显式抛出 NULL。
[规则 M15-1-3] 空抛出语句 (throw;) 仅能在 catch 处理块的复合语句中使用。
[规则 M15-3-1] 仅能在程序启动后、终止前抛出异常。
[规则 M15-3-3] 类构造函数或析构函数的函数 try 块实现中,处理程序不得引用该类或其基类的非静态成员。
[规则 M15-3-4] 代码中显式抛出的每个异常,在所有可能触发该异常的调用路径上,都必须有兼容类型的异常处理程序。
[规则 M15-3-6] 同一个 try-catch 语句或函数 try 块中,若同时提供了派生类及其部分或全部基类的异常处理程序,处理程序必须按派生程度从高到低的顺序排列。
[规则 M15-3-7] 同一个 try-catch 语句或函数 try 块中提供多个异常处理程序时,任何省略号全捕获处理程序必须放在最后。
预处理指令
[规则 A16-0-1] 预处理器仅能用于无条件或条件文件包含、头文件保护宏,以及本规范指定的特定指令。
[规则 A16-2-1] 头文件名或 #include 指令中,不得出现 '、"、/*、//、\ 字符。
[规则 A16-2-2] 不得存在未使用的 #include 指令。
[规则 A16-2-3] 文件中使用的每个符号,都必须显式添加对应的 #include 指令。
[规则 A16-6-1] 不得使用 #error 指令。
[规则 A16-7-1] 不得使用 #pragma 指令。
[规则 M16-0-1] 文件中的 #include 指令,之前只能出现其他预处理指令或注释。
[规则 M16-0-2] 宏只能在全局命名空间中进行 #define 或 #undef。
[规则 M16-0-5] 函数式宏的参数,不得包含看起来像预处理指令的标记。
[规则 M16-0-6] 函数式宏的定义中,每个参数实例都必须用括号包裹(作为 # 或 ## 运算符的操作数时除外)。
[规则 M16-0-7] 未定义的宏标识符,不得在 #if 或 #elif 预处理指令中使用,作为 defined 运算符的操作数时除外。
[规则 M16-0-8] 若 # 符号出现在行首,则其后必须紧跟预处理标记。
[规则 M16-1-1] defined 预处理运算符只能以两种标准形式之一使用。
[规则 M16-1-2] 所有 #else、#elif 和 #endif 预处理指令,必须与其对应的 #if 或 #ifdef 指令位于同一文件中。
[规则 M16-2-3] 必须为头文件提供头文件保护宏。
[规则 M16-3-1] 单个宏定义中,# 或 ## 运算符最多只能出现一次。
[规则 M16-3-2] 不应使用 # 和 ## 运算符。
标准库概述
[规则 A17-0-1] 不得定义、重定义或取消定义 C++ 标准库中的保留标识符、宏和函数。
[规则 A17-1-1] C 标准库的使用必须进行封装与隔离。
[规则 A17-6-1] 不得向标准命名空间中添加非标准实体。
[规则 M17-0-2] 不得重复使用标准库宏和对象的名称。
[规则 M17-0-3] 不得重写标准库函数的名称。
[规则 M17-0-5] 不得使用 setjmp 宏和 longjmp 函数。
语言支持库
[规则 A18-0-1] 只能通过 C++ 库头文件访问 C 库功能。
[规则 A18-0-2] 必须检查字符串转数值的转换操作的错误状态。
[规则 A18-0-3] 不得使用 <clocale>(locale.h) 库和 setlocale 函数。
[规则 A18-1-1] 不得使用 C 风格数组。
[规则 A18-1-2] 不得使用 std::vector<bool> 特化版本。
[规则 A18-1-3] 不得使用 std::auto_ptr。
[规则 A18-1-4] 指向对象数组元素的指针,不得传递给单个对象类型的智能指针。
[规则 A18-1-6] 所有针对用户自定义类型的 std::hash 特化,必须拥有 noexcept 的函数调用运算符。
[规则 A18-5-1] 不得使用 malloc、calloc、realloc 和 free 函数。
[规则 A18-5-2] 不得使用非定位 new 或 delete 表达式。
[规则 A18-5-3] delete 运算符的形式,必须与分配内存时使用的 new 运算符形式匹配。
[规则 A18-5-4] 若项目全局定义了带尺寸或无尺寸的 operator delete 版本,则必须同时定义带尺寸和无尺寸两个版本。
[规则 A18-5-5] 内存管理函数必须满足以下要求:(a) 行为可确定,具备可预估的最坏执行时间;(b) 避免内存碎片;(c) 避免内存耗尽;(d) 避免分配与释放不匹配;(e) 不依赖于内核的非确定性调用。
[规则 A18-5-7] 若项目中使用了非实时实现的动态内存管理函数,则只能在程序的非实时阶段执行内存分配与释放。
[规则 A18-5-8] 生命周期不超过函数作用域的对象,应使用自动存储期。
[规则 A18-5-9] 动态内存分配与释放函数的自定义实现,必须满足 C++ 标准中对应 “必需行为” 条款规定的语义要求。
[规则 A18-5-10] 定位 new 仅能作用于具备正确内存对齐、且存储空间充足的指针。
[规则 A18-5-11] “operator new” 与 “operator delete” 必须成对定义。
[规则 A18-9-1] 不得使用 std::bind。
[规则 A18-9-2] 向其他函数转发值时,必须遵循以下规则:(1) 若值为右值引用,使用 std::move;(2) 若值为转发引用,使用 std::forward。
[规则 A18-9-3] 不得对声明为 const 或 const & 的对象使用 std::move。
[规则 A18-9-4] 作为 std::forward 实参的变量,在转发后不得再被使用。
[规则 M18-0-3] 不得使用 <cstdlib> 库中的 abort、exit、getenv 和 system 函数。
[规则 M18-0-4] 不得使用 <ctime> 库中的时间处理函数。
[规则 M18-0-5] 不得使用 <cstring> 库中的无边界函数。
[规则 M18-2-1] 不得使用 offsetof 宏。
[规则 M18-7-1] 不得使用 <csignal> 库中的信号处理功能。
诊断库
[规则 M19-3-1] 不得使用错误指示器 errno。
通用工具库
[规则 A20-8-1] 不得将已被拥有的指针值,存储到无关的智能指针中。
[规则 A20-8-2] 必须使用 std::unique_ptr 表达独占所有权。
[规则 A20-8-3] 必须使用 std::shared_ptr 表达共享所有权。
[规则 A20-8-4] 无需共享所有权时,必须优先使用 std::unique_ptr 而非 std::shared_ptr。
[规则 A20-8-5] 必须使用 std::make_unique 构造 std::unique_ptr 管理的对象。
[规则 A20-8-6] 必须使用 std::make_shared 构造 std::shared_ptr 管理的对象。
[规则 A20-8-7] 必须使用 std::weak_ptr 表达临时的共享所有权。
字符串库
[规则 A21-8-1] 字符处理函数的参数,必须能表示为 unsigned char 类型。
容器库
[规则 A23-0-1] 迭代器不得隐式转换为 const_iterator。
[规则 A23-0-2] 只能通过有效的引用、迭代器和指针访问容器元素。
算法库
[规则 A25-1-1] 谓词函数对象中,与对象自身标识相关的状态型非静态数据成员或捕获值,不得被拷贝。
[规则 A25-4-1] 关联容器、STL 排序及相关算法使用的排序谓词,必须满足严格弱序关系。
随机数生成
[规则 A26-5-1] 不得使用 std::rand() 生成伪随机数。
[规则 A26-5-2] 随机数引擎不得使用默认初始化。
输入输出库
[规则 A27-0-1] 来自独立组件的输入必须进行校验。
[规则 A27-0-2] C 风格字符串必须保证有足够的空间存储数据和空终止符。
[规则 A27-0-3] 文件流上的交替读写操作之间,必须执行刷新或定位操作,否则不得执行。
[规则 A27-0-4] 不得使用 C 风格字符串。
[规则 M27-0-1] 不得使用 <cstdio> 流输入输出库。