内联函数有什么好处?
在 C++ 中使用内联函数的优点/缺点是什么? 我发现它只会提高编译器输出的代码的性能,但是有了当今优化的编译器、快速的 CPU、巨大的内存等(不像 1980 年那样,内存稀缺,所有东西都必须放入 100KB 内存中)他们今天真的有优势吗?
What is the advantages/disadvantages of using inline functions in C++? I see that it only increases performance for the code that the compiler outputs, but with today's optimized compilers, fast CPUs, huge memory etc. (not like in the 1980< where memory was scarce and everything had to fit in 100KB of memory) what advantages do they really have today?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
优点
缺点
内联魔法
return 42 ;
语句,这对我来说是极端内联,这在现实生活中很少发生,它会使编译时间更长。不会让你的代码变得臃肿,并且会让你的代码更快。 但就像圣杯一样,不要尝试将它应用到任何地方,因为大多数处理都无法通过这种方式解决...不过,无论如何,这很酷...:-p
Advantages
Disadvantages
Inlining Magic
return 42 ;
statement. This is for me extreme inlining. It happens rarely in real life, it makes compilation time longer, will not bloat your code, and will make your code faster. But like the grail, don't try to apply it everywhere because most processing cannot be resolved this way... Still, this is cool anyway...:-p
内联函数速度更快,因为您不需要将参数和返回地址等内容推入/弹出堆栈; 但是,它确实会使您的二进制文件稍大一些。
它有显着差异吗? 对于大多数人来说,在现代硬件上还不够明显。 但它可以带来改变,这对某些人来说已经足够了。
将某些内容标记为内联并不能保证它会内联。 这只是给编译器的一个建议。 有时这是不可能的,例如当您有虚函数或涉及递归时。 有时编译器只是选择不使用它。
我可以看到这样的情况会产生明显的差异:
Inline functions are faster because you don't need to push and pop things on/off the stack like parameters and the return address; however, it does make your binary slightly larger.
Does it make a significant difference? Not noticeably enough on modern hardware for most. But it can make a difference, which is enough for some people.
Marking something inline does not give you a guarantee that it will be inline. It's just a suggestion to the compiler. Sometimes it's not possible such as when you have a virtual function, or when there is recursion involved. And sometimes the compiler just chooses not to use it.
I could see a situation like this making a detectable difference:
在古老的 C 和 C++ 中,
inline
就像register
:向编译器提供关于可能的优化的建议(只不过是建议)。在现代 C++ 中,
inline
告诉链接器,如果在不同的翻译单元中找到多个定义(而不是声明),那么它们都是相同的,链接器可以自由保留一个并丢弃所有其他定义。如果在头文件中定义了一个函数(无论多么复杂或“线性”),则
inline
是必需的,以允许多个源包含该函数,而不会导致链接器出现“多重定义”错误。默认情况下,类内部定义的成员函数是“内联”的,模板函数也是如此(与全局函数相反)。
请注意,将 fileA.h 包含到两个 .cpp 文件中,从而产生两个
afunc()
实例。链接器将丢弃其中之一。
如果没有指定
inline
,链接器将会抱怨。In archaic C and C++,
inline
is likeregister
: a suggestion (nothing more than a suggestion) to the compiler about a possible optimization.In modern C++,
inline
tells the linker that, if multiple definitions (not declarations) are found in different translation units, they are all the same, and the linker can freely keep one and discard all the other ones.inline
is mandatory if a function (no matter how complex or "linear") is defined in a header file, to allow multiple sources to include it without getting a "multiple definition" error by the linker.Member functions defined inside a class are "inline" by default, as are template functions (in contrast to global functions).
Note the inclusion of fileA.h into two .cpp files, resulting in two instances of
afunc()
.The linker will discard one of them.
If no
inline
is specified, the linker will complain.内联是给编译器的一个建议,编译器可以忽略它。 它非常适合小段代码。
如果您的函数是内联的,它基本上会插入到对其进行函数调用的代码中,而不是实际调用单独的函数。 这可以提高速度,因为您不必进行实际的呼叫。
它还可以帮助 CPU 进行流水线操作,因为它们不必使用由调用引起的新指令重新加载流水线。
唯一的缺点是可能会增加二进制大小,但是只要函数很小,这就不会有太大影响。
如今,我倾向于将此类决定留给编译器(无论如何,都是聪明的编译器)。 编写它们的人往往对底层架构有更详细的了解。
Inlining is a suggestion to the compiler which it is free to ignore. It's ideal for small bits of code.
If your function is inlined, it's basically inserted in the code where the function call is made to it, rather than actually calling a separate function. This can assist with speed as you don't have to do the actual call.
It also assists CPUs with pipelining as they don't have to reload the pipeline with new instructions caused by a call.
The only disadvantage is possible increased binary size but, as long as the functions are small, this won't matter too much.
I tend to leave these sorts of decisions to the compilers nowadays (well, the smart ones anyway). The people who wrote them tend to have far more detailed knowledge of the underlying architectures.
内联函数是编译器使用的优化技术。 我们可以简单地在函数原型前面添加 inline 关键字来使函数内联。 内联函数指示编译器在代码中使用该函数的任何位置插入该函数的完整主体。
优点:-< /strong>
它不需要函数调用开销。
它还节省了函数调用时变量入栈/出栈的开销。
它还节省了函数返回调用的开销。
它通过利用指令缓存来增加引用的局部性。
如果指定的话,内联编译器还可以应用程序内优化。 这是最重要的,这样编译器现在可以专注于死代码消除,可以更加注重分支预测、归纳变量消除等。
要查看更多信息,可以点击此链接
http://tajendrasengar.blogspot.com/2010 /03/what-is-inline-function-in-cc.html
Inline function is the optimization technique used by the compilers. One can simply prepend inline keyword to function prototype to make a function inline. Inline function instruct compiler to insert complete body of the function wherever that function got used in code.
Advantages :-
It does not require function calling overhead.
It also save overhead of variables push/pop on the stack, while function calling.
It also save overhead of return call from a function.
It increases locality of reference by utilizing instruction cache.
After in-lining compiler can also apply intra-procedural optimization if specified. This is the most important one, in this way compiler can now focus on dead code elimination, can give more stress on branch prediction, induction variable elimination etc..
To check more about it one can follow this link
http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html
我想补充一点,当您构建共享库时,内联函数至关重要。 如果不标记函数内联,它将以二进制形式导出到库中。 如果导出的话,它也会出现在符号表中。 另一方面,内联函数不会导出,既不会导出到库二进制文件,也不会导出到符号表。
当打算在运行时加载库时,这可能很重要。 它还可能会影响二进制兼容感知库。 在这种情况下,不要使用内联。
I'd like to add that inline functions are crucial when you are building shared library. Without marking function inline, it will be exported into the library in the binary form. It will be also present in the symbols table, if exported. On the other side, inlined functions are not exported, neither to the library binaries nor to the symbols table.
It may be critical when library is intended to be loaded at runtime. It may also hit binary-compatible-aware libraries. In such cases don't use inline.
inline
允许您将函数定义放置在头文件中,并#include
该头文件放置在多个源文件中,而不会违反单一定义规则。inline
allows you to place a function definition in a header file and#include
that header file in multiple source files without violating the one definition rule.在优化期间,许多编译器将内联函数,即使您没有标记它们。 通常,如果您知道编译器不知道的内容,则只需将函数标记为内联,因为它通常可以自行做出正确的决定。
During optimization many compilers will inline functions even if you didn't mark them. You generally only need to mark functions as inline if you know something the compiler doesn't, as it can usually make the correct decision itself.
一般来说,现在任何现代编译器担心内联任何东西几乎都是浪费时间。 编译器实际上应该通过自己对代码的分析以及传递给编译器的优化标志的规范来为您优化所有这些注意事项。 如果您关心速度,请告诉编译器优化速度。 如果您关心空间,请告诉编译器优化空间。 正如另一个答案所提到的,如果确实有意义,一个像样的编译器甚至会自动内联。
此外,正如其他人所说,使用内联并不能保证任何内容的内联。 如果你想保证它,你必须定义一个宏而不是一个内联函数来做到这一点。
何时内联和/或定义宏以强制包含? - 仅当已知对应用程序整体性能有影响的代码关键部分的速度已得到证明且必要时得到证实。
Generally speaking, these days with any modern compiler worrying about inlining anything is pretty much a waste of time. The compiler should actually optimize all of these considerations for you through its own analysis of the code and your specification of the optimization flags passed to the compiler. If you care about speed, tell the compiler to optimize for speed. If you care about space, tell the compiler to optimize for space. As another answer alluded to, a decent compiler will even inline automatically if it really makes sense.
Also, as others have stated, using inline does not guarantee inline of anything. If you want to guarantee it, you will have to define a macro instead of an inline function to do it.
When to inline and/or define a macro to force inclusion? - Only when you have a demonstrated and necessary proven increase in speed for a critical section of code that is known to have an affect on the overall performance of the application.
这不仅仅与性能有关。 C++ 和 C 都用于嵌入式编程,位于硬件之上。 例如,如果您要编写一个中断处理程序,则需要确保代码可以立即执行,而无需交换额外的寄存器和/或内存页。 这就是内联派上用场的时候。 当需要速度时,好的编译器会自行进行一些“内联”,但“内联”迫使它们这样做。
It is not all about performance. Both C++ and C are used for embedded programming, sitting on top of hardware. If you would, for example, write an interrupt handler, you need to make sure that the code can be executed at once, without additional registers and/or memory pages being being swapped. That is when inline comes in handy. Good compilers do some "inlining" themselves when speed is needed, but "inline" compels them.
将函数内联到 so 库中也遇到了同样的麻烦。 看来内联函数没有编译到库中。 因此,如果可执行文件想要使用库的内联函数,链接器会发出“未定义的引用”错误。 (发生在我用 gcc 4.5 编译 Qt 源代码时。
Fell into the same trouble with inlining functions into so libraries. It seems that inlined functions are not compiled into the library. as a result the linker puts out a "undefined reference" error, if a executable wants to use the inlined function of the library. (happened to me compiling Qt source with gcc 4.5.
为什么不默认将所有函数设置为内联? 因为这是一个工程权衡。 至少有两种类型的“优化”:加速程序和减少程序的大小(内存占用)。 内联通常会加快速度。 它消除了函数调用开销,避免了从堆栈中推入然后拉出参数。 然而,它也使程序的内存占用更大,因为现在每个函数调用都必须替换为函数的完整代码。 让事情变得更加复杂的是,请记住 CPU 将经常使用的内存块存储在 CPU 的缓存中,以实现超快速访问。 如果您使程序的内存映像足够大,您的程序将无法有效地使用缓存,并且在最坏的情况下,内联实际上可能会减慢您的程序速度。 在某种程度上,编译器可以计算出权衡是什么,并且可能比您仅查看源代码做出更好的决策。
Why not make all functions inline by default? Because it's an engineering trade off. There are at least two types of "optimization": speeding up the program and reducing the size (memory footprint) of the program. Inlining generally speeds things up. It gets rid of the function call overhead, avoiding pushing then pulling parameters from the stack. However, it also makes the memory footprint of the program bigger, because every function call must now be replaced with the full code of the function. To make things even more complicated, remember that the CPU stores frequently used chunks of memory in a cache on the CPU for ultra-rapid access. If you make the program's memory image big enough, your program won't be able to use the cache efficiently, and in the worst case inlining could actually slow your program down. To some extent the compiler can calculate what the trade offs are, and may be able to make better decisions than you can, just looking at the source code.
我们的计算机科学教授敦促我们永远不要在 C++ 程序中使用内联。 当被问及原因时,他友好地向我们解释说,现代编译器应该自动检测何时使用内联。
所以,是的,内联可以是一种可以在任何可能的情况下使用的优化技术,但显然,只要有可能内联函数,这显然已经为您完成了。
Our computer science professor urged us to never use inline in a c++ program. When asked why, he kindly explained to us that modern compilers should detect when to use inline automatically.
So yes, the inline can be an optimization technique to be used wherever possible, but apparently this is something that is already done for you whenever it's possible to inline a function anyways.
来自另一个讨论的结论:
有什么缺点吗内联函数?
显然,使用内联函数没有任何问题。
但值得注意的是以下几点!
过度使用内联实际上会使程序变慢。 根据函数的大小,内联它可能会导致代码大小增加或减少。 内联一个非常小的访问器函数通常会减少代码大小,而内联一个非常大的函数会显着增加代码大小。 在现代处理器上,由于更好地利用指令缓存,较小的代码通常运行得更快。 - Google 指南
内联函数的速度优势随着函数规模的增大而趋于减小。 在某些时候,与函数体的执行相比,函数调用的开销变得很小,并且失去了好处- 来源
在少数情况下内联函数可能不起作用:
__inline仅当您指定优化选项时,
关键字才会导致函数内联。 如果指定了优化,则是否遵循 __inline 取决于内联优化器选项的设置。 默认情况下,只要运行优化器,内联选项就会生效。 如果指定 optimize ,并且希望忽略__inline
关键字,则还必须指定 noinline 选项。 -来源Conclusion from another discussion here:
Are there any drawbacks with inline functions?
Apparently, There is nothing wrong with using inline functions.
But it is worth noting the following points!
Overuse of inlining can actually make programs slower. Depending on a function's size, inlining it can cause the code size to increase or decrease. Inlining a very small accessor function will usually decrease code size while inlining a very large function can dramatically increase code size. On modern processors smaller code usually runs faster due to better use of the instruction cache. - Google Guidelines
The speed benefits of inline functions tend to diminish as the function grows in size. At some point the overhead of the function call becomes small compared to the execution of the function body, and the benefit is lost - Source
There are few situations where an inline function may not work:
The
__inline
keyword causes a function to be inlined only if you specify the optimize option. If optimize is specified, whether or not__inline
is honored depends on the setting of the inline optimizer option. By default, the inline option is in effect whenever the optimizer is run. If you specify optimize , you must also specify the noinline option if you want the__inline
keyword to be ignored. -Source