gcc 4.7和递归constexpr函数

时间:2013-01-20 00:37:09

标签: c++ recursion c++11 constexpr gcc4.7

我正在使用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将编译时或运行时的递归函数实现的规则是什么?

2 个答案:

答案 0 :(得分:1)

声明函数constexpr并不意味着它将在编译时进行评估。这意味着它可以用于计算编译时所需的值。在任何其他上下文中,它只是一个普通函数,它将在运行时进行求值,除非编译器确定在编译时对其进行评估满足“as-if”规则,并且值得做。

换句话说,如果你将constexpr排除在阶乘函数的声明之外,我希望你能找到完全相同的编译时/运行时执行模式。

答案 1 :(得分:1)

如果在编译时需要,

constexpr仅保证在编译时进行评估。例如,这保证在编译时计算,因为enum值必须是常量:

enum { VALUE = factorial(X) };
cout << VALUE << endl;

在编译时不需要它的任何情况下,它与将其声明为inline具有相同的效果:它只是一个提示,编译器可以自由地做它想要的。

就像inline一样,现在大多数编译器都会完全忽略你的提示。出于性能原因,编译器希望能够在没有要求的情况下内联内容,并且有自己的算法来确定它何时是不值得的,为什么会这样做呢?还在查看inline关键字?