我知道内联是对编译器的提示或请求,其用于避免函数调用的开销。
那么,在什么基础上可以确定一个函数是否适合内联呢?在这种情况下,应避免内联?
我知道内联是对编译器的提示或请求,其用于避免函数调用的开销。
那么,在什么基础上可以确定一个函数是否适合内联呢?在这种情况下,应避免内联?
Answers:
避免函数调用的代价只是故事的一半。
做:
inline
代替#define
inline
:更快的代码和更小的可执行文件(更多的机会保留在代码缓存中)别:
在开发库时,为了使将来的类可扩展,您应该:
请记住,inline
关键字是对编译器的提示:编译器可以决定不内联函数,并且可以决定内联未标记的函数inline
。我通常会避免标记功能inline
(除了编写非常小的功能时)。
关于性能,明智的方法是(一如既往)分析应用程序,然后最终 inline
一组代表瓶颈的功能。
参考文献:
编辑:Bjarne Stroustrup,C ++编程语言:
可以将一个函数定义为
inline
。例如:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
该
inline
说明符向编译器提示,编译器应尝试为fac()
内联调用生成代码,而不是先为该函数放置代码,然后再通过通常的函数调用机制进行调用。聪明的编译器可以720
为调用生成常量fac(6)
。相互递归的内联函数,是否依赖于输入进行递归的内联函数等的可能性,使得无法保证inline
实际上对函数的每次调用都是内联的。无法规范编译器的智能程度,因此一个编译器可能会生成720
,另一个会生成,6 * fac(5)
而另一个会进行非内联调用fac(6)
。为了在没有异常聪明的编译和链接功能的情况下使内联成为可能,内联函数的定义(而不仅仅是声明)必须在范围内(第9.2节)。一个
inline
especifier不影响功能的语义。特别是,内联函数仍然具有唯一的地址,因此static
内联函数的变量(第7.1.2节)也是如此。
EDIT2:ISO-IEC 14882-1998,7.1.2功能说明符
具有
inline
说明符的函数声明(8.3.5、9.3、11.4)声明内联函数。内联说明符向实现指示,在调用点处对函数体进行内联替换比通常的函数调用机制更好。在调用时不需要执行此内联替换的实现;但是,即使省略了此内联替换,仍应遵守7.1.2定义的其他内联函数规则。
inline
不仅仅是对编译器的提示。它更改了有关多个定义的语言规则。同样,拥有静态数据也不是避免内联函数的铸铁理由。无论是否声明该函数,实现都必须为每个函数static分配一个静态对象inline
。如果类具有内联构造函数和虚拟析构函数,则它们仍可扩展。空括号析构函数是一个虚拟函数,有时保持内联是一个好主意。
inline
的函数中的静态函数,结果是该函数没有内联:您为调用付出了代价,并且包括并调用该函数的每个翻译单元都获得了自己的代码和静态变量的副本。开发库时不内联构造函数和析构函数的原因是与您的库的未来版本具有二进制兼容性
inline
如果编译器感觉非函数可以内联。而inline
如果编译器决定不内联函数它们不会被内联。正如Charles Bailey所说,它改变了语言规则。与其将其视为优化提示,不如将其视为完全不同的概念更为准确。该inline
关键字告诉编译器允许多个定义,而不是其他。“内联”优化几乎可以应用于任何功能,无论是否已标记inline
。
inline
,为了获得函数内联,我们并没有全部使用。有时我们想要其他好处,例如绕过ODR。
inline
与优化几乎没有关系。 inline
是一个指令,指示编译器如果给定的函数定义在程序中多次出现,则不产生错误,并且保证该定义将在每次使用的转换中出现,并且在出现的任何位置都具有完全相同的定义。
给定以上规则,inline
它适用于短函数,这些短函数的主体不需要在声明中仅包含需要的依赖项。每次遇到定义时,都必须对其进行解析,并且可能会生成其主体的代码,因此,这意味着在单个源文件中仅定义一次的函数上会产生一些编译器开销。
编译器可以内联(即用执行该功能操作的代码替换对该功能的调用)它选择的任何功能调用。过去的情况是,它“显然”无法内联一个未在与调用相同的转换单元中声明的函数,但是随着链接时间优化的使用不断增加,即使现在这不是事实。同样的事实是标记的功能inline
可能无法内联。
inline
关键字有什么关系?什么是快乐的巧合?
告诉编译器内联函数是一种优化,最重要的优化规则是过早的优化是万恶之源。始终编写清晰的代码(使用高效的算法),然后分析程序并仅优化花费时间太长的函数。
如果您发现某个特定的函数非常简短,简单,并且在一个紧密的内部循环中被调用了成千上万次,则可能是个不错的选择。
但是,您可能会感到惊讶-许多C ++编译器会自动为您内联小函数-并且它们也可能会忽略您的内联请求。
/FAcs
在Visual Studio中,-s
在GCC中)以查看其功能。以我的经验,这两个编译器都非常重视inline关键字。
inline
关键字。也就是说,如果您看到该函数已内联,并inline
从中删除了说明符,它仍将内联。如果您有相反的具体例子,请分享!
inline
关键字如何阻碍“清除代码”?“过早优化”中的关键字是过早的,而不是优化。说您应该积极*避免优化只是垃圾。引用的重点是您应该避免不必要的优化,并且会对代码产生有害的副作用(例如,使其难以维护)。我看不到inline
关键字将如何使代码的可维护性降低,或者将其添加到函数中可能有害。
在决定是否使用内联时,我通常会牢记以下想法:在现代计算机上,内存延迟比原始计算可能是更大的瓶颈。众所周知,经常调用内联函数会增大可执行文件的大小。此外,这种功能可以存储在CPU的代码缓存中,当需要访问该代码时,它将减少缓存未命中的次数。
因此,您必须自己决定:内联会增大还是减小生成的机器代码的大小?调用该函数将导致高速缓存未命中的可能性有多大?如果在整个代码中都采用这种方式,那么我会说可能性很高。如果将其限制为单个紧密循环,则可能性很低。
在列出下面的情况下,我通常使用内联。但是,如果您真正关心性能,则必须进行性能分析。此外,您可能想检查编译器是否真正接受了提示。
此外,在维护大型项目时,内联方法具有严重的副作用。更改内联代码后,使用该代码的所有文件将由编译器自动重建(它是一个好的编译器)。这可能会浪费您的大量开发时间。
当inline
方法转移到源文件并且不再内联时,必须重新构建整个项目(至少这是我的经验)。以及将方法转换为内联时。
inline
,都没有关系(除了没有inline
关键字之外,您会收到链接器错误-但inline
关键字不是导致过度重建的问题。)
我已经阅读了一些答案,看到缺少一些东西。
我使用的规则是不要使用内联,除非我希望它是内联的。看起来很傻,现在解释。
编译器足够聪明,短函数总是内联的。除非程序员说要这样做,否则永远不要将长函数作为内联函数使用。
我知道内联是对编译器的提示或请求
实际上inline
是编译器的命令,它别无选择,并且after inline
关键字使所有代码都内联。所以你永远不能使用inline
关键字,编译器将设计最短的代码。
所以什么时候用 inline
?
如果要内联一些代码,请使用。我只知道一个例子,因为我只在一种情况下使用它。这是用户身份验证。
例如我有这个功能:
inline bool ValidUser(const std::string& username, const std::string& password)
{
//here it is quite long function
}
无论此功能有多大,我都希望将其内联,因为它会使我的软件更难以破解。
inline
对C ++新手来说是什么CFLAGS
,对Gentoo新手来说是什么:不,使用进行编译-O3 -funroll-loops -finline-functions
不会使您的旧奔腾飞起来;)