Ash*_*win 132 c c++ compiler-construction
inline int factorial(int n)
{
if(!n) return 1;
else return n*factorial(n-1);
}
Run Code Online (Sandbox Code Playgroud)
在我阅读本文时,发现如果编译器没有正确处理上述代码会导致"无限编译".
编译器如何决定是否内联函数?
Der*_*ark 134
首先,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);
}
Run Code Online (Sandbox Code Playgroud)
进入这段代码:
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们基本上将函数内联了3次.有些编译器会执行此优化.我记得MSVC++有一个设置来调整将在递归函数上执行的内联级别(我相信最多20个).
Mat*_*t J 23
实际上,如果您的编译器不能智能地执行操作,它可能会尝试inline递归地插入您的d函数的副本,从而创建无限大的代码.然而,大多数现代编译器都会认识到这一点.他们可以:
对于案例2,许多编译器都#pragma可以设置为指定应该执行此操作的最大深度.在gcc中,您也可以从命令行传入此命令--max-inline-insns-recursive(请参阅此处的更多信息).