内联函数不能包含递归、go to循环等



在一本教科书中,我读到内联函数不能包含递归,go to,循环等。为什么?我不认为它会产生语法错误,如果我这样做。

你的课本错了。

首先,理解"将函数声明为inline"的概念与实际的"函数调用内联"之间的区别是很重要的。前者适用于函数本身,而后者独立适用于每个调用。

现在,内联函数可以包含任何东西。几乎对任何函数的任何直接调用都可以内联。没有任何限制。

包含循环或局部goto的内联代码显然没有问题。所以,当你的书说内联函数"不能包含循环或gotos"时,它一定是指某些特定的(可能是非常旧的)编译器的怪癖,由于某些特定的实现原因,这些编译器不能内联这样的函数。

递归是另一回事。显然,如果在编译时不知道递归深度,则不可能完全内联所有嵌套递归调用。然而,仍然有可能将递归"展开"到特定的有限深度。也就是说,编译器可以内联递归调用,比如5层,然后继续进行真正的(非内联的)递归调用。这与被称为"循环展开"的优化技术没有太大区别。所以,即使递归函数也可以内联。有些编译器甚至可以让你控制递归函数的内联展开深度。

这段代码是完全有效的:

class Test 
{
  public:
    inline void sayHello(int i);
};
void Test::sayHello(int i)
{
  std::cout << "Hello "<< i << std::endl;
  if (i>0)
    sayHello(i-1);
}
int main(int argc, char** argv) {
    Test t;
    t.sayHello(10);
}

. .并按预期递归。

4.6.3

(GCC)

在这种情况下,函数没有内联,因为内联只是对编译器的一个提示。不需要。

在上面的评论中,你会发现一个更完整的答案:递归函数可以内联吗?

这听起来像是c++的内联函数概念和内联扩展函数调用的优化之间的混淆。

内联函数是在每个使用它的翻译单元中定义的函数;与非内联函数不同,非内联函数必须根据单一定义规则在一个翻译单元中定义。这些函数的功能没有特别的限制;特别是,它们可以像你说的那样递归地调用自己。

内联函数和优化之间的联系是,许多编译器在编译调用站点时需要定义可用;这通常要求函数是内联的,以便在多个翻译单元中有一个定义。

这本书的意思可能是说递归调用不能内联展开,因为这意味着生成的代码必须包含自身的副本;那是不可能的。但是仍然没有理由为什么它不应该包含循环,分支或任何其他正常的流控制语句。

正如Mike所说,语言定义对inline函数没有这样的限制。你有时会看到一个编译器警告说,一个函数没有内联展开,因为它使用了一些编译器不会内联的语言结构,比如递归、循环等。这是,只有告诉您函数没有内联展开,因此您没有得到您可能想要的优化。代码是有效的,生成的可执行文件将正常工作。

我们可以在内联函数中使用循环、递归等。但是为了一个好的编程实践,我们不会这样做;因为每一个在循环中执行的指令都必须由你的CPU来管理。它会消耗你内存中的一些额外空间。

最新更新