C++26新增erroneous behavior:与undefined behavior的区别及新增原因
C++ Erroneous Behavior 详解:定义、差异与标准新增原因
一、什么是Erroneous Behavior?
Erroneous Behavior(错误行为)是C++26标准新增的行为分类,指程序执行了标准明确判定为错误的操作,但标准既不强制编译器必须诊断该错误,也不对程序后续的执行状态做任何硬性约束。简单说就是:标准告诉你“这么做是错的”,但没说编译器必须拦你,也没说程序接下来会怎么样。
二、和Undefined Behavior的核心区别
两者最关键的差异在于错误的明确性和标准对它们的定位:
- 触发场景:
- Erroneous Behavior:所有触发场景都是标准逐条明确列出的错误操作,比如某些违反类型安全的隐式转换、非法的模板特化细节等(具体参考C++26标准的对应条款)。
- Undefined Behavior(未定义行为):指标准完全没有给出定义的操作,比如数组越界访问、空指针解引用的部分情况——标准根本没说这些操作是对是错,也不管后果。
- 编译器义务:
- Erroneous Behavior:编译器可以选择是否给出警告或错误提示,但不是必须的。
- Undefined Behavior:编译器通常没有任何义务诊断,很多时候编译能通过,但运行时可能出任何问题。
- 后果约束:
- Erroneous Behavior:虽然标准不强制后续行为,但它本质是“标准盖章的错误”,编译器可以假设这类操作不会发生来做优化,但不会像UB那样允许极端操作(比如直接删除整个函数的代码)。
- Undefined Behavior:后果完全无限制,编译器能生成任何代码,甚至编译阶段直接崩溃,或者运行时出现完全不可预测的结果。
三、和现有行为类型的差异
C++原本有三类行为分类:Undefined Behavior、Unspecified Behavior(未指定行为)、Implementation-defined Behavior(实现定义行为),新增的Erroneous Behavior和它们的区别如下:
- vs 未指定行为:
未指定行为是标准允许编译器从多个合法选项里选一个,比如函数参数的求值顺序——所有可能的结果都是符合标准的,程序本身没做错。而Erroneous Behavior是程序干了标准认定的错事,属于非法操作。 - vs 实现定义行为:
实现定义行为是标准把具体逻辑交给编译器,但要求编译器必须把行为写进文档(比如sizeof(long)的大小),而且这些行为都是合法的。Erroneous Behavior是错误操作,编译器不需要文档化后续行为,也没有合法的处理选项。 - vs 未定义行为:
再强调一次:UB是标准没覆盖的灰色地带,Erroneous是标准明确标记的错误。另外,UB的后果完全无约束,而Erroneous的后果虽然也不固定,但编译器一般不会做太极端的优化,毕竟标准明确这是错误,但没授权彻底的任意行为。
四、C++26新增该类型的原因
- 填补分类空白:之前C++标准里,有些操作明显是错的,但又没法归到UB(因为UB是“未定义”,不是“明确错误”),也不属于另外两类合法行为。新增Erroneous Behavior可以把这类情况明确归类,让标准的行为体系更严谨。
- 给编译器划清优化边界:对于明确的错误操作,编译器可以选择诊断,或者在假设这类操作不会发生的前提下做优化,但又不会像UB那样允许过度优化(避免出现开发者难以调试的诡异问题)。
- 帮助开发者定位问题:当程序触发Erroneous Behavior时,开发者能明确知道这是标准认定的错误,而非“未定义”的模糊情况,排查问题时方向更清晰。
- 标准化现有实践:很多编译器早就对一些明确的错误操作给出警告了,新增这个分类可以把这些厂商实践标准化,让不同编译器的行为更一致,减少跨平台的坑。
内容的提问来源于stack exchange,提问作者Jan Schultke
相关产品推荐
相关产品推荐

