如果递归函数被定义为内联,会发生什么?

7

可能是重复问题:
递归函数可以内联吗?

我认为将递归函数定义为内联将没有任何效果,也不会被完全内联。因为编译器不知道要复制内联函数的代码级别。有什么想法吗?


同样相关的内容:https://dev59.com/vXVD5IYBdhLWcg3wRpaX - Hans Passant
3个回答

3

我尝试查找相关的Stack Overflow问题,为您找到一个明确的答案,但遗憾的是...

所以,关键字inline(或成员函数在类定义中隐式定义为inline)有两个作用:

  • 保证函数可以在多个翻译单元中定义,而不违反“一次定义规则”,即实际上,没有链接器对多个定义抱怨。为此,所有函数定义都必须是inline,并且它们必须相同。

  • 它作为模糊的提示,通知编译器将函数调用的机器代码内联。某些调用可能会被内联,而其他调用则不会。内联的程度可能会有所不同,甚至可能完全忽略此提示(实际上,g ++倾向于跟随提示到荒谬和可能不好的程度,而Visual C ++更像是忽略了这一点)。

对于递归函数,如果编译器遵循任何特定函数调用的提示,则该调用可能会扩展到一到两个,三个或任意级别的递归。这是一件棘手的事情,所以不要指望它。此外,编译器自身的内联启发式算法可能比您的直觉更好,因为编译器拥有更全局的事物视图(它知道更多),所以总结一下:

不要使用inline作为提示效果,而应将其用于ODR保证。

如果您确信自己比编译器更了解,并且已遵守“先测量”和“不进行过早优化”之类的原则,则可以通过编译器特定的语言扩展或预处理指令来获得更可靠的控制内联的能力。

祝一切顺利!


2
显然,它无法无限重复代码。可能有一种有限的方法来实现,类似于循环展开,但那可能比一个简单的 for(int i=0; i < 5; ++i) 循环更难以由编译器确定。
如果函数被特殊地编码,编译器还可以使用 尾调用。虽然它不会在调用点逐字节地重复汇编代码,但它可以避免设置堆栈帧和 call 函数,并将其替换为只有一个 jmp 指令,使函数调用的开销不亚于一个 if 语句。

0

哦,那我就投票关闭它。 - Etienne de Martel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接