G++ 编译器是否在未使用返回值的情况下将 constexpr 函数视为常规函数?
does g++ compiler treats constexpr functions as regular in a case their return value isnt being used?
我试图查看由g ++编译的cpp constexpr函数的编译代码。 我看到,如果函数不返回任何内容,编译器会将其视为常规函数,但如果它返回一个值并且我将此值分配给 constexpr 变量,则只有在编译时才会计算它。
代码示例:
constexpr int func(int x){
return x!=0 ? 1: throw "Error";
}
int main(){
func(2);
}
和编译器输出:
push rbp
mov rbp, rsp
mov edi, 2
call func(int)
mov eax, 0
pop rbp
ret
如您所见,它在运行时调用 func。相反,如果我将函数结果断言为 constexpr:
constexpr int func(int x){
return x!=0 ? 1: throw "Error";
}
int main(){
constexpr int x = func(2);
}
和编译器输出:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 1
mov eax, 0
pop rbp
ret
有人可以解释为什么编译器在编译时而不是运行时需要此赋值来评估函数吗?
允许编译器决定是否在编译时或运行时计算 constexpr 函数。仅当函数在需要编译时常量表达式(例如使用结果初始化constexpr
变量(的上下文中使用时,编译器才必须在编译时计算函数。
在您的第一个示例中,情况并非如此,并且您可能在调试模式下编译,该函数在运行时调用,就像其他所有函数一样。
引用cpp偏好(由我突出显示(:
constexpr 说明符声明可以在编译时计算函数或变量的值。然后,可以在只允许编译时常量表达式的情况下使用此类变量和函数(前提是给出了适当的函数参数(。
如果您编译您的第一个示例,例如-O3
,您将看到函数调用已优化。
我编译了下面的代码,以了解 gcc 11.2 是否优化了 constexpr 函数:
#include <iostream>
using namespace std;
constexpr double pi(){
double a=0.;
for(int i=1;i<100000;i+=4)a+=1./i-1./(i+2);
return a*4;
}
int main(){
constexpr int pi2=pi()*100;
enum {pi3=pi2};
cout<<pi3<<endl;
}
反汇编如下:
# temp.cpp:10: int main(){
call __main #
# temp.cpp:11: constexpr int pi2=pi()*100;
movl $314, -4(%rbp) #, pi2
# temp.cpp:13: cout<<pi3<<endl;
movl $314, %edx #,
movq .refptr._ZSt4cout(%rip), %rax #, tmp85
movq %rax, %rcx # tmp85,
call _ZNSolsEi #
movq %rax, %rcx #, _1
# temp.cpp:13: cout<<pi3<<endl;
movq .refptr._ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_(%rip), %rax #, tmp86
movq %rax, %rdx # tmp86,
call _ZNSolsEPFRSoS_E #
# temp.cpp:14: }
movl $0, %eax #, _7
addq $48, %rsp #,
popq %rbp #
ret
因此,gcc 可以在编译时评估 constexpr 函数。
如果需要更长的计算时间,则应增加 gcc 标志-fconstexpr-*
。但我观察到编译时计算比(-O3
标志(执行时间计算花费更多的时间。
如果需要更长的计算,我建议,
- 编写代码以生成代码(如上面示例中的计算
pi
(, - 编译并运行该代码,
- 将生成的代码与其余代码一起编译。
编写makefile
来执行上述步骤会有所帮助。
相关文章:
- 条件constexpr函数
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- constexpr构造函数需要常量成员函数时出现问题
- constexpr 函数获取常量字符*
- 如何在 constexpr 函数中实现回退运行时
- 为什么我不能在 constexpr lambda 函数中使用 std::tuple
- 在非 constexpr 函数中作为左值传递的变量上使用 'constexpr' 函数
- 在 constexpr 构造函数 (c++17) 中赋值到 const char * 在使用 Android NDK 时
- NVCC 错误:string_view.h:constexpr 函数返回是非常量
- constexpr函数中的静态constexpr变量
- 在 constexpr funnction 中调用basic_string函数
- 为什么我的 constexpr 对象在我的函数中不是 constexpr?
- constexpr log10 整数函数
- C++:初始化 constexpr 构造函数中的成员数组
- 编译器生成的默认构造函数具有 constexpr 混淆行为
- 在 constexpr 构造函数中初始化数组是否合法?
- 在 constexpr 函数中断言
- MSVC 和函数参数的 constexpr?
- 具有位域的结构的 Constexpr 构造函数
- C++ 默认构造函数 constexpr 或正确未定义