我正在阅读有关constexpr
here的信息:
constexpr
说明符声明可以在编译时评估函数或变量的值。
当我第一次读到这句话时,对我来说这很有意义。但是,最近我遇到了一些使我完全失望的代码。我在下面重建了一个简单的例子:
#include <iostream>
void MysteryFunction(int *p);
constexpr int PlusOne(int input) {
return input + 1;
}
int main() {
int i = 0;
MysteryFunction(&i);
std::cout << PlusOne(i) << std::endl;
return 0;
}
看这段代码,我没有办法说PlusOne(i)
的结果应该是什么,但是实际上它可以编译! (当然,链接将失败,但是g++ -std=c++11 -c
成功,而不会出现错误。)
“可能在编译时评估函数值”的正确解释是什么?
答案 0 :(得分:11)
在满足常量表达式求值的其他要求的情况下,可以在常量表达式中调用constexpr
函数 。它也可以在不是常量表达式的表达式中调用,在这种情况下,其行为与未使用constexpr
声明的行为相同。如您问题中的代码所示,调用constexpr
函数的结果不是自动一个常量表达式。
答案 1 :(得分:8)
在某种意义上,引用的措词有点误导。如果仅将PlusOne
隔离起来,观察其逻辑,并假设输入在编译时是已知的,则其中的计算也可以在编译时执行。在其上拍上constexpr
关键字可确保我们保持这种可爱的状态并且一切正常。
但是,如果在编译时不知道输入 ,那么它仍然只是一个普通函数,将在运行时被调用。
因此constexpr
是该函数的属性(“对于某些输入不是所有输入的”可能在编译时求值” )您在这种情况下的功能/输入组合(因此对于该特定输入也不是 )。
这有点像一个函数如何使用const int&
,但这并不意味着原始对象必须为const
。这里,类似地,constexpr
在函数上添加了约束,而在函数的输入上没有添加约束。
诚然,这都是一个巨大的,令人困惑的,模糊的混乱(C ++!是的!)。请记住,您的代码描述了程序的含义!在编译的不同阶段,这不是机器指令的直接配方。
(要真正执行此操作,您可以将整数作为模板参数。)
答案 2 :(得分:7)
“可能在编译时评估函数值”的正确解释是什么?
如果在编译时可以评估函数的所有参数,则可以在编译时评估函数的返回值。
但是,如果仅在运行时知道函数参数的值,则只能在运行时评估函数的retun值。
因此,可能在编译时评估函数的值,但这不是必需的。
答案 3 :(得分:4)
所有答案都是正确的,但我想举一个简短的例子,用来解释constexpr多么荒谬,不直观。
#include <cstdlib>
constexpr int fun(int i){
if (i==42){
return 47;
} else {
return rand();
}
}
int main()
{
int arr[fun(42)];
}
请注意: 有些人认为constexpr的状态不令人满意,因此他们提议在语言中添加constexpr!关键字。