正如用户 Tony 指出的那样,C++ 标准的第 1.3.12 段中有一个 [Note] 说
允许的未定义行为的范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现......
这是否与 UB 的定义相矛盾,即……本国际标准没有要求?我的意思是他们说“没有要求”,然后说“允许的 UB”——就在同一段中。
应该如何解释这个注释?它确实以任何方式限制了UB吗?
来自ISO/IEC 指令第 3 部分的§6.5.1 :
集成在标准文本中的注释和示例仅用于提供旨在帮助理解或使用标准的附加信息,并且不应包含为声称符合标准而必须遵守的规定标准。
因此,它完全是非规范性的(不具约束力),仅用于可能的澄清。
由于注释不是规范的,它不会以任何方式限制 UB。这只是一个说明,一个实现可以使用一些正式导致 UB 作为文档扩展的构造,尽管任何依赖这种细节的程序当然本质上不能安全地移植到其他环境。
本说明解释了如果一个实现遇到没有定义行为的代码时可能会做什么。“允许”这个词并不是一种限制,而是给出了一些常见行为的例子。
有趣的是,编译器几乎总是必须编译一些东西!考虑这段代码:
void f() { 1 / 0; }
译者遇到这种情况时的行为没有明确定义,但它不能随心所欲!事实上,如果它是一个编译器,它仍然需要编译这个编译单元。那是因为包含这个函数的程序的行为仍然可以很好地定义!编译器无法知道函数是否被调用。事实上,这个问题出现在函数是“main()”的地方,并且控制肯定会通过零除法,结果是编译器甚至不允许拒绝该程序。原因是:程序仍然是格式良好的,并且要求符合标准的编译器接受所有格式良好的程序(并拒绝所有格式错误的程序并发出诊断错误消息,除非另有说明)。
这不能很容易地形成错误,因为很难准确地指定智能编译器在检测何时必须发生除以零时需要多么智能。
如此有趣的是,该标准声称“不施加任何要求”实际上几乎是错误的。支持单独编译的编译系统的特性是它无法检测没有明确定义的行为的一段代码是否实际上已执行,因此编译器实际上无论如何都需要编译某些东西,因为它不能推断程序是否具有未定义的行为。