我正在使用constexpr
递归进行一些尝试并尝试查看它是如何编译的,我不明白在gcc
选择在编译时或运行时计算递归的情况时间。
我正在使用以下阶乘计算代码:
#include <iostream>
constexpr unsigned int factorial(unsigned int i)
{
return i > 0 ? i*factorial(i-1) : 1;
}
int main(void)
{
std::cout << factorial(X) << std::endl;
}
我更改了factorial中的值x
。
-O1
标志进行编译时,表达式仍未在编译时计算。-O2
,表达式在编译时计算x < 9
。在此值之后,factorial以内联方式实现为循环。更改-fconstexpr-depth
标志的值不会改变任何事情。 -O3
,表达式在编译时if x < 7
计算。在此值之后,factorial以x86 xmm扩展名实现。10000
或更多的编译时间计算,减少或增加-fconstexpr-depth
的值不会改变任何内容。有谁知道gcc 4.7将编译时或运行时的递归函数实现的规则是什么?
答案 0 :(得分:1)
声明函数constexpr
并不意味着它将在编译时进行评估。这意味着它可以用于计算编译时所需的值。在任何其他上下文中,它只是一个普通函数,它将在运行时进行求值,除非编译器确定在编译时对其进行评估满足“as-if”规则,并且值得做。
换句话说,如果你将constexpr
排除在阶乘函数的声明之外,我希望你能找到完全相同的编译时/运行时执行模式。
答案 1 :(得分:1)
constexpr
仅保证在编译时进行评估。例如,这保证在编译时计算,因为enum
值必须是常量:
enum { VALUE = factorial(X) };
cout << VALUE << endl;
在编译时不需要它的任何情况下,它与将其声明为inline
具有相同的效果:它只是一个提示,编译器可以自由地做它想要的。
就像inline
一样,现在大多数编译器都会完全忽略你的提示。出于性能原因,编译器希望能够在没有要求的情况下内联内容,并且有自己的算法来确定它何时是不值得的,为什么会这样做呢?还在查看inline
关键字?