我知道内联是对编译器的提示或请求,用于避免函数调用开销。

那么,在什么基础上可以确定一个函数是否是内联的候选人? 在哪种情况下应该避免内联?


当前回答

内联与优化关系很小。内联是给编译器的指令,如果给定的函数定义在程序中多次出现,则不会产生错误,并承诺该定义将出现在使用它的每次翻译中,并且在出现它的任何地方都具有完全相同的定义。

根据上述规则,内联适用于短函数,其函数体不需要包含超出声明所需的额外依赖项。每次遇到定义时,都必须对其进行解析,并可能生成其主体的代码,因此对于在单个源文件中只定义一次的函数,这意味着一些编译器开销。

编译器可以内联(即用执行该函数操作的代码替换对函数的调用)它选择的任何函数调用。过去的情况是,它“显然”不能内联一个没有在同一个翻译单元中声明的函数,但随着链接时间优化的使用越来越多,现在这种情况也不存在了。同样正确的是,标记为内联的函数可能不是内联的。

其他回答

最好的方法是分析你的程序,把那些被多次调用并消耗CPU周期的小函数标记为内联函数。这里的关键字是“小”——一旦函数调用开销与函数中花费的时间相比可以忽略不计,那么内联它们就没有意义了。

我建议的另一种用法是,如果你有一些小函数在性能关键代码中经常被调用,以至于缓存不相关,你可能也应该内联这些函数。同样,这也是侧写师应该能够告诉你的。

在决定是否使用内联时,我通常记住以下想法:在现代机器上,内存延迟可能是比原始计算更大的瓶颈。众所周知,经常调用的内联函数会增加可执行文件的大小。此外,这样的函数可以存储在CPU的代码缓存中,当需要访问代码时,这将减少缓存失败的数量。

因此,您必须自己决定:内联是否会增加或减少生成的机器代码的大小?调用该函数会导致缓存丢失的可能性有多大?如果它遍布整个代码,那么我认为可能性很高。如果它被限制在一个单一的紧密循环,那么可能性很低。

我通常使用内联的情况下,我列出如下。然而,当您真正关心性能时,概要分析是必不可少的。此外,您可能希望检查编译器是否真的接受了提示。

在紧密循环中调用的简短例程。 非常基本的访问器(get / set)和包装器函数。 不幸的是,头文件中的模板代码会自动获得内联提示。 像宏一样使用的短代码。(例如min() / max()) 简短的数学程序。

内联函数可以通过消除将参数推入堆栈的需要来提高代码性能。 如果有问题的函数在你的代码的关键部分,你应该在项目的优化部分做出内联而不是内联的决定,

你可以在c++ FAQ中阅读更多关于内联的内容

我通常遵循一个拇指规则,我用3-4个简单的语句作为内联函数。但最好记住,这只是给编译器的一个提示。最终是否使它内联的调用仅由编译器执行。如果有超过这些语句,我不会用一个愚蠢的编译器进行内联声明,这可能会导致代码膨胀。

最好的方法是检查和比较生成的内联和非内联指令。但是,省略内联总是安全的。使用内联可能会导致您不想要的麻烦。