C++ 中内联函数的好处?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/145838/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Benefits of inline functions in C++?
提问by Lennie De Villiers
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?
在 C++ 中使用内联函数的优点/缺点是什么?我看到它只会提高编译器输出的代码的性能,但是有了今天优化的编译器、快速的 CPU、巨大的内存等(不像 1980 年<内存稀缺,所有东西都必须放在 100KB 内存中)什么他们今天真的有优势吗?
采纳答案by Brian R. Bondy
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:
我可以看到这样的情况产生了可检测的差异:
inline int aplusb_pow2(int a, int b) {
return (a + b)*(a + b) ;
}
for(int a = 0; a < 900000; ++a)
for(int b = 0; b < 900000; ++b)
aplusb_pow2(a, b);
回答by paercebal
Advantages
好处
- By inlining your code where it is needed, your program will spend less time in the function call and return parts. It is supposed to make your code go faster, even as it goes larger (see below). Inlining trivial accessors could be an example of effective inlining.
- By marking it as inline, you can put a function definition in a header file (i.e. it can be included in multiple compilation unit, without the linker complaining)
- 通过在需要的地方内联您的代码,您的程序将在函数调用和返回部分上花费更少的时间。它应该让你的代码运行得更快,即使它变得更大(见下文)。内联琐碎的访问器可能是有效内联的一个例子。
- 通过将其标记为内联,您可以将函数定义放在头文件中(即它可以包含在多个编译单元中,而链接器不会抱怨)
Disadvantages
缺点
- It can make your code larger (i.e. if you use inline for non-trivial functions). As such, it could provoke paging and defeat optimizations from the compiler.
- It slightly breaks your encapsulation because it exposes the internal of your object processing (but then, every "private" member would, too). This means you must not use inlining in a PImpl pattern.
- It slightly breaks your encapsulation 2: C++ inlining is resolved at compile time. Which means that should you change the code of the inlined function, you would need to recompile all the code using it to be sure it will be updated (for the same reason, I avoid default values for function parameters)
- When used in a header, it makes your header file larger, and thus, will dilute interesting informations (like the list of a class methods) with code the user don't care about (this is the reason that I declare inlined functions inside a class, but will define it in an header after the class body, and never inside the class body).
- 它可以使您的代码更大(即,如果您对非平凡函数使用内联)。因此,它可能会引发分页并破坏编译器的优化。
- 它稍微破坏了你的封装,因为它暴露了你的对象处理的内部(但是,每个“私有”成员也会如此)。这意味着您不能在 PImpl 模式中使用内联。
- 它稍微破坏了您的封装 2:C++ 内联在编译时解决。这意味着如果您更改内联函数的代码,您需要使用它重新编译所有代码以确保它会被更新(出于同样的原因,我避免了函数参数的默认值)
- 当在头文件中使用时,它会使你的头文件更大,因此,会用用户不关心的代码稀释有趣的信息(如类方法的列表)(这就是我在内部声明内联函数的原因)类,但将在类主体之后的标题中定义它,而不是在类主体内部)。
Inlining Magic
内联魔法
- The compiler may or may not inline the functions you marked as inline; it may also decide to inline functions not marked as inline at compilation or linking time.
- Inline works like a copy/paste controlled by the compiler, which is quite different from a pre-processor macro: The macro will be forcibly inlined, will pollute all the namespaces and code, won't be easily debuggable, and will be done even if the compiler would have ruled it as inefficient.
- Every method of a class defined inside the body of the class itself is considered as "inlined" (even if the compiler can still decide to not inline it
- Virtual methods are not supposed to be inlinable. Still, sometimes, when the compiler can know for sure the type of the object (i.e. the object was declared and constructed inside the same function body), even a virtual function will be inlined because the compiler knows exactly the type of the object.
- Template methods/functions are not always inlined (their presence in an header will not make them automatically inline).
- The next step after "inline" is template metaprograming . I.e. By "inlining" your code at compile time, sometimes, the compiler can deduce the final result of a function... So a complex algorithm can sometimes be reduced to a kind of
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
- 编译器可能会也可能不会内联您标记为内联的函数;它还可能决定在编译或链接时内联未标记为内联的函数。
- 内联的工作方式类似于编译器控制的复制/粘贴,这与预处理器宏有很大的不同:宏将被强制内联,会污染所有命名空间和代码,不容易调试,甚至会完成如果编译器会认为它效率低下。
- 在类自身内部定义的类的每个方法都被视为“内联”(即使编译器仍然可以决定不内联它)
- 虚拟方法不应该是内联的。尽管如此,有时,当编译器可以确定地知道对象的类型(即对象是在同一个函数体内声明和构造的)时,即使是虚函数也会被内联,因为编译器确切地知道对象的类型。
- 模板方法/函数并不总是内联的(它们在标题中的存在不会使它们自动内联)。
- “内联”之后的下一步是模板元编程。即通过在编译时“内联”您的代码,有时,编译器可以推断出函数的最终结果......因此,有时可以将复杂的算法简化为一种
return 42 ;
语句。这对我来说是极端的内联。它在现实生活中很少发生,它使编译时间更长,不会使您的代码膨胀,并使您的代码更快。但是就像圣杯一样,不要尝试将它应用到任何地方,因为大多数处理无法通过这种方式解决...不过,无论如何这很酷...
:-p
回答by Emilio Garavaglia
In archaic C and C++, inline
is like register
: a suggestion (nothing more than a suggestion) to the compiler about a possible optimization.
在古老的 C 和 C++ 中,inline
就像register
:向编译器提供有关可能优化的建议(不过是建议)。
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.
在现代 C++ 中,inline
告诉链接器,如果在不同的翻译单元中发现多个定义(不是声明),它们都是相同的,链接器可以自由地保留一个并丢弃所有其他的。
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.
inline
如果在头文件中定义了一个函数(无论多么复杂或“线性”),则是强制性的,以允许多个源包含它而不会导致链接器出现“多重定义”错误。
Member functions defined inside a class are "inline" by default, as are template functions (in contrast to global functions).
默认情况下,在类中定义的成员函数是“内联的”,模板函数也是如此(与全局函数相反)。
//fileA.h
inline void afunc()
{ std::cout << "this is afunc" << std::endl; }
//file1.cpp
#include "fileA.h"
void acall()
{ afunc(); }
//main.cpp
#include "fileA.h"
void acall();
int main()
{
afunc();
acall();
}
//output
this is afunc
this is afunc
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.
请注意将 fileA.h 包含在两个 .cpp 文件中,从而产生了两个 .cpp 实例afunc()
。链接器将丢弃其中之一。如果没有inline
指定,链接器会抱怨。
回答by paxdiablo
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.
它还可以帮助 CPU 进行流水线操作,因为它们不必使用由调用引起的新指令重新加载流水线。
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.
我现在倾向于将这些类型的决定留给编译器(好吧,无论如何都是聪明的)。编写它们的人往往对底层架构有更详细的了解。
回答by TSS
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.
内联函数是编译器使用的优化技术。可以简单地在函数原型前添加 inline 关键字来使函数内联。内联函数指示编译器在代码中使用该函数的任何地方插入函数的完整主体。
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
要了解更多信息,可以点击此链接 http://tajendrasengar.blogspot.com/2010/03/what-is-inline-function-in-cc.html
回答by doc
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.
当打算在运行时加载库时,这可能很关键。它也可能会影响二进制兼容的库。在这种情况下,不要使用内联。
回答by Ferruccio
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.
inline
允许您将函数定义放在一个头文件中,并将#include
该头文件放在多个源文件中,而不会违反一个定义规则。
回答by Devrin
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.
在优化过程中,即使您没有标记函数,许多编译器也会内联函数。如果您知道编译器不知道的事情,您通常只需要将函数标记为内联函数,因为它通常可以自己做出正确的决定。
回答by Tall Jeff
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.
何时内联和/或定义宏以强制包含?- 只有当您对已知对应用程序的整体性能有影响的关键代码部分的速度进行了证明和必要的证明时。
回答by J.M. Stoorvogel
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.
这不仅仅是关于性能。C++ 和 C 都用于嵌入式编程,位于硬件之上。例如,如果您要编写中断处理程序,则需要确保代码可以立即执行,而无需交换额外的寄存器和/或内存页。这就是内联派上用场的时候。当需要速度时,好的编译器会自己做一些“内联”,但“内联”会强迫它们。