我遇到了以下主张:
实际上,在计算常量表达式时,需要捕获该语言中所有形式的 UB(尽管标准库中的 UB 不需要捕获)。只有运行时 UB 才可能发生任何事情。
(强调我的)
我的问题是上述说法在技术上正确吗?
在询问用户标准如何强加这一点时,他们引用了expr.const#5.8,其中指出:
5.表达式 E 是核心常量表达式,除非对 E 的计算遵循抽象机 ([intro.execution]) 的规则,将计算以下其中一项:
5.8. 具有 [intro] 到 [cpp] 中指定的未定义行为的操作;
但在阅读了上面的[expr.const#5.8]之后,我无法弄清楚这如何意味着在计算常量表达式时需要捕获语言中所有形式的 UB。那么有人可以澄清这个引文如何支持(如果支持的话)上面引用的评论中提出的主张吗?
我还读过这样的内容:
如果行为未定义,编译器可以接受它,拒绝它,发出警告,并根据标准,甚至在您的计算机上崩溃、挂起或安装病毒。
因此,在我看来(在阅读第一条评论后),常量表达式求值期间的 UB 和运行时 UB 之间存在根本区别。
真相是什么?
在这里剥离评论
3 [intro.defs],3.65 [defns.undef]说
常量表达式 ([expr.const]) 的求值永远不会表现出在 [intro] 到 [cpp] 中明确指定为未定义的行为
不过,通读[expr.const],我并不清楚立即函数中的每个语句都被定义为常量表达式。
如果 consteval 函数中的代码尝试显式描述为 UB 的行为,那么编译器可以表现出 UB 吗?
consteval void f() {
int x;
int y;
&x - &y; // UB allowed? or diagnostic required?
}
Run Code Online (Sandbox Code Playgroud)