我昨天发了一个帖子,但我认为它不清楚,得到的回复根本没有解决我的困惑。所以,我会尽量让这个例子更简单。
为什么允许这样做:
constexpr int incr(int k1)
{
return k1 + 5;
}
constexpr int foo(int k) // runs in compile time
{
return incr(k);
}
int main() {
constexpr int x = 5;
constexpr int y = foo(4);
}
...但是这个非常相似的功能不是吗?
constexpr int incr(int k1)
{
return k1 + 5;
}
constexpr int foo(int k) // runs in compile time
{
constexpr int x = incr(k); // k: not a constant expression
return x;
}
int main() {
constexpr int x = 5;
constexpr int y = foo(4);
}
在不断评估的情况下,这两个函数究竟有何不同?对我来说,它们看起来几乎完全一样,除了一个立即返回而另一个首先计算值并将其分配给 constexpr 变量。
如果可以,也请参考标准,以便我进一步阅读!
constexpr
修饰符,当应用于函数时,仅给出函数在编译时运行的 possibility (此外,在 C++23 草案中, constexpr
函数不再受到以前的限制,因此你最好把它当作合同来读,作者给出的支持constexpr
语义的“承诺”)。修饰符并没有取消这个事实,即相同的函数也可能在运行时运行:
int main() {
constexpr int compileVar = foo(2);
int param = 4;
int runtimeVar = foo(param);
}
因此不能保证传递给
constexpr
函数的参数在编译时被评估。
另一方面,
constexpr
修饰符,当应用于 variables 时,only 在编译时被评估,并且编译器合理地阻止您使用函数的(可能)运行时参数来评估编译-时间变量。
在不断评估的情况下,这两个函数究竟有何不同?
我认为这里的主要误解是,如果函数在编译时求值,则
constexpr
函数的所有部分都在编译时求值,无论内部变量是否具有 constexpr
修饰符。所以这个函数的正确等价物:
constexpr int foo(int k)
{
return incr(k);
}
会是:
constexpr int foo(int k)
{
int x = incr(k);
return x;
}