“内联”的利弊

时间:2010-10-08 07:28:43

标签: c++

首先,我想说明我所知道的关于'内联'的事实,这样你就不必费心了。

  1. 内联函数是一种特殊的函数,其定义必须在使用该函数的每个翻译单元中都可用。
  2. 这是一个提示编译器(它可以自由忽略)的提示,省略函数调用,并扩展正文而不是调用。
  3. 我所知道的唯一专业是(2.)可以使代码更快。
  4. 我唯一知道的是(1)是否增加了不良的耦合。
  5. 现在让我们考虑模板。如果我有一个模板库,我需要在每个翻译单元中提供功能模板的定义,对吧?让我们忘记有争议的“出口”一段时间,因为它无论如何都没有真正解决问题。 所以,我得出一个结论,没有理由将内联模板函数设置为内联,因为我所知道的内联的唯一内容是先验的。

    如果我错了,请纠正我。 提前谢谢。

4 个答案:

答案 0 :(得分:11)

  

我所知道的唯一的专业是(2.)可以使代码更快。

可能是操作词。内联函数可以使某些代码路径更快,是的。

但内联函数会给大多数现代CPU上的指令缓存带来额外压力。如果你的函数太大而无法放入L1指令缓存中,那么可能 实际运行更慢而不是执行函数调用(CPU可以通过预取函数来优化它)它的返回网站)。

内联函数也可能对L2缓存施加不适当的压力 - 如果内联函数的使用次数非常多,额外的代码大小将增加缓存未命中的可能性,导致长时间延迟和流水线停顿CPU歪着拇指等待内存总线做某事。

inline远非银弹。具有积极优化的编译器将完全忽略inline提示,因为他们将根据启发式选择内联函数,例如代码大小或分支的存在,而不管inline关键字的存在与否

  

我唯一知道的是(1)增加了不良的耦合。

这是我从未听过的。 “耦合”是我在描述代码的高级关系时所听到的概念。这更像是代码的可维护性和通用性问题。 inline是低级代码生成的问题。

对于模板,如果其启发式显示出这样做的优势,那么积极优化的编译器将会内联。

但是,有一个链接级问题需要考虑:您可能需要声明一个函数或模板inline(或static,具体取决于具体情况),以便消除重复的符号链接时间或限制符号可见性。当然,这不是优化。

总之,除非特别要求,否则不要使用inline关键字。

答案 1 :(得分:1)

我认为你不应该在模板函数定义之前编写inline。我认为无论你是否提出要求,大多数编译器都会内联小函数。有些编译器甚至能够在链接时为仅在一个翻译单元中定义的函数执行此操作。

Imho,inline关键字的唯一要点是能够在标题内定义非模板函数,对于那些没有在链接时内联的编译器(或者只需要“标题”)库)。

答案 2 :(得分:1)

您不需要在每个翻译中提供定义 - 只有使用它们的用户;)

无论你是否内联声明它们, 无关紧要。编译器可能会确认您使用关键字(或其他强制内联声明)。编译器可以从模板定义生成导出的类/函数。如果有人问我是否默认内联(知道他们不知道使用它的效果),我会说:“不要使用它”,因为编译器对你的程序有了更好的理解。编译器之间的优化方式不同。

示例:

  • 让我们说编译器根据您的要求内联一些功能
  • 在优化过程中内联扩展通常会在一定数量的指令中出现... oops - 编译器只是突然显示它应该内联的内容,因为这些模板的主体太大了这是默认的内联。
  • 或者你最终可能会得到一个超大的二进制文件

因此,当您默认内联时,您只能将一只手绑在编译器的后面(前提是它当然承认您使用了关键字)。

一般来说:如果你不知道,请相信编译器(编写者)。

在某些情况下我默认声明内联(即使它只是为了减少导出的符号)。

内联的其他好处:

  • 内联可以使代码/功能更小
  • 内联可以减少导出符号的数量
  • 它也可以让编译器做出更好的优化,因为它能够在优化过程中“看到”更多的程序。

答案 3 :(得分:0)

通过内联,它消除了创建和销毁新堆栈帧的开销,并跳转到exe中的另一个位置。这使代码变得更快。

当然,缺点是exe大小的增加,因为函数必须在任何地方被调用。

修改

内联函数仅在多次调用且函数大小较小时才有用。否则,文件大小的增加实际上可能使程序变慢,而且实际上不值得。