在 cppreference 上我看到了 ub 的说法i = ++i + i++
,记得在编译阶段似乎无法执行带有 ub 的代码,我决定通过抛出一些简单的代码来检查一下:
#include <iostream>
constexpr int func(int i){
i = ++i + i++;
return i;
}
constexpr int glob_i = func(1);
int main()
{
std::cout << glob_i << "\n"; // выводит 4
return 0;
}
我不明白为什么这不会导致编译错误?如果编译通过,为什么运行时的类似计算会给出结果 5?
godbolt 上的示例:https://godbolt.org/z/rM8b7szz5
cppreference 上的文章,一切从这里开始https://en.cppreference.com/w/cpp/language/eval_order
根据[expr.const] §10.8,如果表达式导致 NB(未定义行为),那么它就不再是constexpr表达式:
并且在[intro.defs] §3.65中还提到:
那些。事实上,您的constexpr函数调用 NP 并不意味着它本身会导致编译错误。它将不再是constexpr (即,它只在运行时起作用)。
但是如果您尝试将此函数的值分配给constexpr变量,则它应该已经导致编译错误。例如:
我们可以看到,所有 3 个主要编译器都出现错误:https://godbolt.org/z/4bzd8YvvG
但是编译器不能总是可靠地确定一个函数的行为是否是NP。我怀疑这就是你的情况。让我们来看一个简化版本:
奇怪的是,所有 3 个编译器都可以工作:https://godbolt.org/z/Ta8j6Tsz9
也就是说,在第一个例子中,编译器可以准确地确定 NP,但在第二个例子中却不能。这就是为什么gcc和clang只给出诊断消息,而msvc完全没有声音……