Gre*_*osz 198
避免函数调用的成本只是故事的一半.
做:
inline而不是#defineinline:更快的代码和更小的可执行文件(更多的机会留在代码缓存中)别:
在开发库时,为了使类在未来可扩展,您应该:
请记住,inline关键字是编译器的提示:编译器可能决定不内联函数,并且可以决定内联inline首先未标记的函数.我通常避免标记功能inline(除非编写非常小的功能).
关于性能,明智的方法是(一如既往)分析应用程序,然后最终inline代表瓶颈的一组函数.
参考文献:
编辑:Bjarne Stroustrup,C++编程语言:
可以将函数定义为
inline.例如:
inline int fac(int n)
{
return (n < 2) ? 1 : n * fac(n-1);
}
Run Code Online (Sandbox Code Playgroud)
该
inline说明符是一种提示,它应该尝试为的呼叫生成代码编译器fac()内联,而不是一次奠定了该函数的代码,然后通过常规的函数调用机制调用.聪明的编译器可以720为调用生成常量fac(6).相互递归的内联函数,依赖于输入的递归或不递归的内联函数的可能性使得无法保证inline函数的每次调用都实际内联.编译器的聪明程度不能立法,因此一个编译器可能会生成720另一个编译器,而另一个编译器可能会生成6 * fac(5)一个非内联调用fac(6).为了在没有异常聪明的编译和链接功能的情况下实现内联,内联函数的定义 - 而不仅仅是声明 - 必须在范围内(第9.2节).一个
inlineespecifier不影响功能的语义.特别是,内联函数仍然具有唯一的地址,因此static内联函数的变量(第7.1.2节)也是如此.
EDIT2:ISO-IEC 14882-1998,7.1.2函数说明符
带有
inline说明符的函数声明(8.3.5,9.3,11.4)声明了一个内联函数.内联说明符向实现指示在调用点处函数体的内联替换优先于通常的函数调用机制.在呼叫点执行此内联替换不需要实现; 但是,即使省略了这种内联替换,仍应遵守7.1.2定义的内联函数的其他规则.
CB *_*ley 56
inline与优化没什么关系.inline如果给定定义的函数在程序中多次出现,并且承诺定义将在每个使用它的转换中发生,并且在它出现的任何地方它将具有完全相同的定义,则指示编译器不产生错误.
鉴于上述规则,inline适用于简短的函数,其主体不需要包括对声明所需的额外依赖性.每次遇到定义时,都必须对其进行解析,并且可能会生成其主体的代码,因此它意味着在单个源文件中仅定义一次的函数会产生一些编译器开销.
编译器可以内联(即用对该函数执行该操作的代码替换对函数的调用)所选择的任何函数调用.过去,它"显然"无法内联未在与调用相同的转换单元中声明的函数,但随着链接时间优化的使用越来越多,即使现在也不是这样.同样正确的是标记的功能inline可能没有内联.
dma*_*oni 10
告诉编译器内联函数是一种优化,最重要的优化规则是过早优化是所有邪恶的根源.始终编写清晰的代码(使用有效的算法),然后分析您的程序,只优化耗时太长的函数.
如果你发现一个特定的函数非常简短,并且它在一个紧密的内循环中被称为成千上万次,它可能是一个很好的候选者.
但是,您可能会感到惊讶 - 许多C++编译器会自动为您编写小函数 - 他们也可能忽略您的内联请求.
过早优化是万恶之源!
根据经验,我通常只内联“getter”和“setter”。一旦代码运行并稳定,分析可以显示哪些函数可以从内联中受益。
另一方面,大多数现代编译器都有很好的优化算法,并且会内联您应该为您内联的内容。
Reasuming——写内联的单行函数,以后再担心其他的。
找出答案的最佳方法是对程序进行概要分析,并标记被多次调用的小函数,并消耗CPU周期为inline。这里的关键字是“ small”(小)-与函数所花费的时间相比,函数调用的开销可以忽略不计,因此内联它们是没有意义的。
我建议的另一种用法是,如果您有一些经常在性能关键代码中调用的小函数足以使高速缓存未命中,那么您也应该内联这些小函数。同样,这是探查器应该能够告诉您的。
| 归档时间: |
|
| 查看次数: |
85814 次 |
| 最近记录: |