递归函数可以内联吗?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (104)
inline int factorial(int n)
{
    if(!n) return 1;
    else return n*factorial(n-1);
}

编译器如何决定是否内联一个函数?

提问于
用户回答回答于

首先,inline函数的规范只是一个提示。编译器可以(而且经常)完全忽略inline限定符。也就是说,编译器内联递归函数,就像它可以展开无限循环一样。它只需对其“展开”函数的级别设置一个限制。

优化编译器可能会转换以下代码:

inline int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    return factorial(x);
}

在此代码中:

int factorial(int n)
{
    if (n <= 1)
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}

int f(int x)
{
    if (x <= 1)
    {
        return 1;
    }
    else
    {
        int x2 = x - 1;
        if (x2 <= 1)
        {
            return x * 1;
        }
        else
        {
            int x3 = x2 - 1;
            if (x3 <= 1)
            {
                return x * x2 * 1;
            }
            else
            {
                return x * x2 * x3 * factorial(x3 - 1);
            }
        }
    }
}

在本例中,我们基本上已经将函数内联了3次。一些编译器执行此优化。

用户回答回答于

实际上,如果编译器不明智地操作,它可能会尝试插入inlined函数递归,创建无限大的代码。然而,大多数现代编译器都会认识到这一点。它们可以:

  1. 一点也不内联这个函数
  2. 将其内联到一定深度,如果到那时它还没有终止,那么使用标准函数调用约定调用函数的单独实例。这可以以高性能的方式处理许多常见的情况,同时为罕见的情况留下一个大调用深度的退路。这也意味着您将保留该函数代码的内联版本和单独版本。

扫码关注云+社区