C++ 中的常量表达式有一个非常简洁的属性:它们的求值不能有未定义的行为(7.7.4.7):
表达式 e 是一个核心常量表达式,除非按照抽象机 ([intro.execution]) 的规则对 e 的求值将求值以下之一:
...
具有未定义行为的操作,如本文档的 [intro] 到 [cpp] [注:包括,例如,有符号整数溢出 ([expr.prop])、某些指针算术 ([expr.add])、除以零,或某些移位操作——尾注];
尝试将值存储13!
在 aconstexpr int
确实会产生一个很好的编译错误:
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
输出:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
for (; n > 1; --n) r *= n;
^
9:23: note: in call to 'f(3)'
constexpr int x = f(13);
^
1 error generated.
(顺便说一句,为什么错误说“调用'f(3)'”,而它是对f(13)的调用?..)
然后,我从 中删除constexpr
,x
但制作f
一个consteval
. 根据文档:
consteval - 指定一个函数是一个立即函数,也就是说,对函数的每次调用都必须产生一个编译时常量
我确实希望这样的程序会再次导致编译错误。但相反,该程序使用 UB 编译和运行。
这是为什么?
UPD:评论者建议这是一个编译器错误。我举报了:https ://bugs.llvm.org/show_bug.cgi?id=43714