我试图查看由 g++ 编译的 cpp constexpr 函数的编译代码。我看到,如果该函数不返回任何内容,编译器将其视为常规函数,但如果它返回一个值并且我将此值分配给 constexpr 变量,则仅在编译时计算它。
代码示例:
constexpr int func(int x){
return x!=0 ? 1: throw "Error";
}
int main(){
func(2);
}
Run Code Online (Sandbox Code Playgroud)
和编译器输出:
push rbp
mov rbp, rsp
mov edi, 2
call func(int)
mov eax, 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
如您所见,它在运行时调用 func。相反,如果我将函数结果赋值给 constexpr:
constexpr int func(int x){
return x!=0 ? 1: throw "Error";
}
int main(){
constexpr int x = func(2);
}
Run Code Online (Sandbox Code Playgroud)
和编译器输出:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 1
mov eax, 0
pop rbp
ret
Run Code Online (Sandbox Code Playgroud)
有人能解释一下为什么编译器需要这个赋值来在编译时而不是在运行时评估函数吗?
允许编译器决定是否在编译时或运行时评估 constexpr 函数。只有在需要编译时常量表达式的上下文中使用该函数(例如constexpr用结果初始化变量)时,编译器才必须在编译时对函数求值。
在您的第一个示例中,情况并非如此,因为您可能在调试模式下编译,该函数在运行时被调用,就像其他所有函数一样。
来自cppreference的引用(由我突出显示):
constexpr 说明符声明可以在编译时评估函数或变量的值。然后可以在仅允许编译时常量表达式的情况下使用此类变量和函数(前提是给出了适当的函数参数)。
如果你用 eg 编译你的第一个例子,-O3你会看到函数调用被优化掉了。