C++ 我应该什么时候为函数/方法编写关键字“内联”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1759300/
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
When should I write the keyword 'inline' for a function/method?
提问by Partial
When should I write the keyword inline
for a function/method in C++?
我什么时候应该inline
在 C++ 中为函数/方法编写关键字?
After seeing some answers, some related questions:
看了一些答案,一些相关的问题:
When should I notwrite the keyword 'inline' for a function/method in C++?
When will the compiler not know when to make a function/method 'inline'?
Does it matter if an application is multithreadedwhen one writes 'inline' for a function/method?
我什么时候不应该在 C++ 中为函数/方法编写关键字“内联”?
编译器何时不知道何时使函数/方法“内联”?
当为函数/方法编写“内联”时,应用程序是否是多线程的有关系吗?
回答by deft_code
Oh man, one of my pet peeves.
哦,天哪,我最讨厌的人之一。
inline
is more like static
or extern
than a directive telling the compiler to inline your functions. extern
, static
, inline
are linkage directives, used almost exclusively by the linker, not the compiler.
inline
更像是static
或extern
不是指令告诉编译器内联您的函数。 extern
, static
,inline
是链接指令,几乎专门由链接器使用,而不是编译器。
It is said that inline
hints to the compiler that you think the function should be inlined. That may have been true in 1998, but a decade later the compiler needs no such hints. Not to mention humans are usually wrong when it comes to optimizing code, so most compilers flat out ignore the 'hint'.
据说inline
向编译器暗示您认为该函数应该内联。这在 1998 年可能是正确的,但十年后编译器不需要这样的提示。更不用说人类在优化代码时通常是错误的,因此大多数编译器完全忽略了“提示”。
static
- the variable/function name cannot be used in other translation units. Linker needs to make sure it doesn't accidentally use a statically defined variable/function from another translation unit.extern
- use this variable/function name in this translation unit but don't complain if it isn't defined. The linker will sort it out and make sure all the code that tried to use some extern symbol has its address.inline
- this function will be defined in multiple translation units, don't worry about it. The linker needs to make sure all translation units use a single instance of the variable/function.
static
- 变量/函数名称不能在其他翻译单元中使用。链接器需要确保它不会意外使用来自另一个翻译单元的静态定义的变量/函数。extern
- 在此翻译单元中使用此变量/函数名称,但如果未定义,请不要抱怨。链接器将把它整理出来并确保所有试图使用某个外部符号的代码都有它的地址。inline
- 这个函数会在多个翻译单元中定义,不用担心。链接器需要确保所有翻译单元都使用变量/函数的单个实例。
Note:Generally, declaring templates inline
is pointless, as they have the linkage semantics of inline
already. However, explicit specialization and instantiation of templates require inline
to be used.
注意:通常,声明模板inline
是没有意义的,因为它们已经具有链接语义inline
。但是,需要inline
使用模板的显式专业化和实例化。
Specific answers to your questions:
对您的问题的具体回答:
When should I write the keyword 'inline' for a function/method in C++?
Only when you want the function to be defined in a header. More exactly only when the function's definition can show up in multiple translation units. It's a good idea to define small (as in one liner) functions in the header file as it gives the compiler more information to work with while optimizing your code. It also increases compilation time.
When should I not write the keyword 'inline' for a function/method in C++?
Don't add inline just because you think your code will run faster if the compiler inlines it.
When will the compiler not know when to make a function/method 'inline'?
Generally, the compiler will be able to do this better than you. However, the compiler doesn't have the option to inline code if it doesn't have the function definition. In maximally optimized code usually all
private
methods are inlined whether you ask for it or not.As an aside to prevent inlining in GCC, use
__attribute__(( noinline ))
, and in Visual Studio, use__declspec(noinline)
.Does it matter if an application is multithreaded when one writes 'inline' for a function/method?
Multithreading doesn't affect inlining in any way.
我应该什么时候为 C++ 中的函数/方法编写关键字“内联”?
仅当您希望在标题中定义函数时。更准确地说,只有当函数的定义可以出现在多个翻译单元中时。在头文件中定义小的(如在一个 liner 中)函数是一个好主意,因为它在优化代码的同时为编译器提供了更多的信息。它还增加了编译时间。
我什么时候不应该在 C++ 中为函数/方法编写关键字“内联”?
不要仅仅因为您认为如果编译器内联您的代码会运行得更快而添加内联。
编译器何时不知道何时使函数/方法“内联”?
通常,编译器将能够比您做得更好。但是,如果没有函数定义,编译器就没有内联代码的选项。在最大程度优化的代码
private
中,无论您是否要求,通常所有方法都是内联的。为了防止在 GCC 中内联,请使用
__attribute__(( noinline ))
,并在 Visual Studio 中使用__declspec(noinline)
.当为函数/方法编写“内联”时,应用程序是否是多线程的有关系吗?
多线程不会以任何方式影响内联。
回答by Alaroff
I'd like to contribute to all of the great answers in this thread with a convincing example to disperse any remaining misunderstanding.
我想通过一个令人信服的例子来为这个线程中的所有优秀答案做出贡献,以消除任何剩余的误解。
Given two source files, such as:
给定两个源文件,例如:
inline111.cpp:
#include <iostream> void bar(); inline int fun() { return 111; } int main() { std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun; bar(); }
inline222.cpp:
#include <iostream> inline int fun() { return 222; } void bar() { std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun; }
inline111.cpp:
#include <iostream> void bar(); inline int fun() { return 111; } int main() { std::cout << "inline111: fun() = " << fun() << ", &fun = " << (void*) &fun; bar(); }
inline222.cpp:
#include <iostream> inline int fun() { return 222; } void bar() { std::cout << "inline222: fun() = " << fun() << ", &fun = " << (void*) &fun; }
Case A:
Compile:
g++ -std=c++11 inline111.cpp inline222.cpp
Output:
inline111: fun() = 111, &fun = 0x4029a0 inline222: fun() = 111, &fun = 0x4029a0
Discussion:
Even thou you ought to have identical definitions of your inline functions, C++ compiler does not flag it if that is not the case (actually, due to separate compilationit has no ways to check it). It is your own duty to ensure this!
Linker does not complain about One Definition Rule, as
fun()
is declared asinline
. However, because inline111.cppis the first translation unit (which actually callsfun()
) processed by compiler, the compiler instantiatesfun()
upon its firstcall-encounter in inline111.cpp. If compiler decides notto expandfun()
upon its call from anywhere else in your program (e.g.from inline222.cpp), the call tofun()
will always be linked to its instance produced from inline111.cpp(the call tofun()
inside inline222.cppmay also produce an instance in that translation unit, but it will remain unlinked). Indeed, that is evident from the identical&fun = 0x4029a0
print-outs.Finally, despite the
inline
suggestion to the compiler to actually expandthe one-linerfun()
, it ignoresyour suggestion completely, which is clear becausefun() = 111
in both of the lines.
案例一:
编译:
g++ -std=c++11 inline111.cpp inline222.cpp
输出:
inline111: fun() = 111, &fun = 0x4029a0 inline222: fun() = 111, &fun = 0x4029a0
讨论:
即使您应该对内联函数具有相同的定义,如果情况并非如此,C++ 编译器也不会对其进行标记(实际上,由于单独编译,它无法检查它)。确保这一点是您自己的责任!
链接器不会抱怨单一定义规则,正如
fun()
声明的那样inline
。然而,由于inline111.cpp是第一个翻译单元(实际上调用fun()
由编译器处理),编译器实例fun()
在其第一次在呼叫遭遇inline111.cpp。如果编译器决定不在fun()
程序中的任何其他地方扩展它的调用(例如从inline222.cpp),则调用fun()
将始终链接到从inline111.cpp生成的实例(对inline222.cppfun()
内部的调用)也可能在该翻译单元中生成一个实例,但它将保持未链接状态)。事实上,从相同的&fun = 0x4029a0
打印输出中可以明显看出这一点。最后,尽管
inline
建议编译器实际扩展one-linerfun()
,但它完全忽略了您的建议,这很明显,因为fun() = 111
在这两行中。
Case B:
Compile(notice reverse order):
g++ -std=c++11 inline222.cpp inline111.cpp
Output:
inline111: fun() = 222, &fun = 0x402980 inline222: fun() = 222, &fun = 0x402980
Discussion:
This case asserts what have been discussed in Case A.
Notice an important point, that if you comment out the actual call to
fun()
in inline222.cpp(e.g.comment outcout
-statement in inline222.cppcompletely) then, despite the compilation order of your translation units,fun()
will be instantiated upon it's first call encounter in inline111.cpp, resulting in print-out for Case Basinline111: fun() = 111, &fun = 0x402980
.
案例B:
编译(注意逆序):
g++ -std=c++11 inline222.cpp inline111.cpp
输出:
inline111: fun() = 222, &fun = 0x402980 inline222: fun() = 222, &fun = 0x402980
讨论:
这个案例断言了在案例 A 中讨论过的内容。
请注意一个重要的观点,如果你注释掉实际调用
fun()
在inline222.cpp(如出注释cout
语句来在inline222.cpp完全),那么,尽管你的翻译单元的编译顺序,fun()
将被实例化后,它在第一次调用相遇inline111.cpp,从而使打印出的情况B作为inline111: fun() = 111, &fun = 0x402980
。
Case C:
Compile(notice -O2):
g++ -std=c++11 -O2 inline222.cpp inline111.cpp
or
g++ -std=c++11 -O2 inline111.cpp inline222.cpp
Output:
inline111: fun() = 111, &fun = 0x402900 inline222: fun() = 222, &fun = 0x402900
Discussion:
- As is described here,
-O2
optimization encourages compiler to actually expandthe functions that can be inlined (Notice also that-fno-inline
is defaultwithout optimization options). As is evident from the outprint here, thefun()
has actually been inline expanded(according to its definition in that particulartranslation unit), resulting in two differentfun()
print-outs. Despite this, there is still only oneglobally linked instance offun()
(as required by the standard), as is evident from identical&fun
print-out.
- As is described here,
案例 C:
编译(注意 -O2):
g++ -std=c++11 -O2 inline222.cpp inline111.cpp
或者
g++ -std=c++11 -O2 inline111.cpp inline222.cpp
输出:
inline111: fun() = 111, &fun = 0x402900 inline222: fun() = 222, &fun = 0x402900
讨论:
- 如此处所述,
-O2
优化鼓励编译器实际扩展可以内联的函数(请注意,这-fno-inline
也是没有优化选项的默认设置)。从这里的输出可以明显看出,fun()
实际上已经内联扩展(根据它在该特定翻译单元中的定义),导致两种不同的fun()
打印输出。尽管如此,仍然只有一个全局链接的实例fun()
(根据标准的要求),从相同的&fun
打印输出中可以明显看出。
- 如此处所述,
回答by BostonLogan
You still need to explicitly inline your function when doing template specialization (if specialization is in .h file)
在进行模板特化时,您仍然需要显式内联函数(如果特化在 .h 文件中)
回答by Aric TenEyck
1) Nowadays, pretty much never. If it's a good idea to inline a function, the compiler will do it without your help.
1)如今,几乎从来没有。如果内联函数是个好主意,编译器会在没有您帮助的情况下完成。
2) Always. See #1.
2)总是。见#1。
(Edited to reflect that you broke your question into two questions...)
(编辑以反映您将您的问题分成两个问题......)
回答by Johannes Schaub - litb
When should I not write the keyword 'inline' for a function/method in C++?
我什么时候不应该在 C++ 中为函数/方法编写关键字“内联”?
If the function is declared in the header and defined in the .cpp
file, you should notwrite the keyword.
如果函数是在头部声明和定义.cpp
文件,你应该不写关键字。
When will the the compiler not know when to make a function/method 'inline'?
编译器何时不知道何时使函数/方法“内联”?
There is no such situation. The compiler cannot make a function inline. All it can do is to inline some or all calls to the function. It can't do so if it hasn't got the code of the function (in that case the linker needs to do it if it is able to do so).
没有这种情况。编译器不能使函数内联。它所能做的就是内联对函数的部分或全部调用。如果它没有获得函数的代码,它就不能这样做(在这种情况下,如果链接器能够这样做,它就需要这样做)。
Does it matter if an application is multithreaded when one writes 'inline' for a function/method?
当为函数/方法编写“内联”时,应用程序是否是多线程的有关系吗?
No, that does not matter at all.
不,这根本没有关系。
回答by meda beda
- When will the the compiler not know when to make a function/method 'inline'?
- 编译器何时不知道何时使函数/方法“内联”?
This depends on the compiler used. Do not blindly trust that nowadays compilers know better then humans how to inline and you should never use it for performance reasons, because it's linkage directive rather than optimization hint. While I agree that ideologically are these arguments correct encountering reality might be a different thing.
这取决于所使用的编译器。不要盲目相信现在的编译器比人类更了解如何内联,并且出于性能原因您永远不应该使用它,因为它是链接指令而不是优化提示。虽然我同意这些论点在意识形态上是否正确,但遇到现实可能是另一回事。
After reading multiple threads around I tried out of curiosity the effects of inline on the code I'm just working and the results were that I got measurable speedup for GCC and no speed up for Intel compiler.
在阅读了多个线程之后,我出于好奇尝试了内联对我正在工作的代码的影响,结果是我获得了可测量的 GCC 加速,而英特尔编译器没有加速。
(More detail: math simulations with few critical functions defined outside class, GCC 4.6.3 (g++ -O3), ICC 13.1.0 (icpc -O3); adding inline to critical points caused +6% speedup with GCC code).
(更多细节:在类之外定义的几个关键函数的数学模拟,GCC 4.6.3 (g++ -O3), ICC 13.1.0 (icpc -O3);向关键点添加内联会导致 GCC 代码加速 6%)。
So if you qualify GCC 4.6 as a modern compiler the result is that inline directive still matters if you write CPU intensive tasks and know where exactly is the bottleneck.
因此,如果您将 GCC 4.6 认定为现代编译器,结果是,如果您编写 CPU 密集型任务并知道瓶颈究竟在哪里,内联指令仍然很重要。
回答by DarkSquid
In reality, pretty much never. All you're doing is suggesting that the compiler make a given function inline (e.g., replace all calls to this function /w its body). There are no guarantees, of course: the compiler may ignore the directive.
实际上,几乎从来没有。您所做的只是建议编译器内联给定的函数(例如,替换对此函数的所有调用/w 其主体)。当然,没有任何保证:编译器可能会忽略该指令。
The compiler will generally do a good job of detecting + optimizing things like this.
编译器通常会很好地检测和优化这样的事情。
回答by Jedzia
gcc by default does not inline any functions when compiling without optimization enabled. I don't know about visual studio – deft_code
默认情况下,gcc 在未启用优化的情况下编译时不会内联任何函数。我不知道visual studio – deft_code
I checked this for Visual Studio 9 (15.00.30729.01) by compiling with /FAcs and looking at the assembly code: The compiler produced calls to member functions without optimization enabled in debugmode. Even if the function is marked with __forceinline, no inline runtime code is produced.
我通过使用 /FAcs 编译并查看汇编代码检查了 Visual Studio 9 (15.00.30729.01) 的这一点:编译器生成了对成员函数的调用,而没有在调试模式下启用优化。即使函数用__forceinline标记,也不会生成内联运行时代码。
回答by Jeremy Morgan
You want to put it in the very beginning, before return type. But most Compilers ignore it. If it's defined, and it has a smaller block of code, most compilers consider it inline anyway.
你想把它放在一开始,在返回类型之前。但大多数编译器忽略它。如果它被定义,并且它的代码块更小,大多数编译器无论如何都会认为它是内联的。
回答by n.caillou
Unless you are writing a library or have special reasons, you can forget about inline
and use link-time optimizationinstead. It removes the requirement that a function definition must be in a header for it to be considered for inlining across compilation units, which is precisely what inline
allows.
除非您正在编写库或有特殊原因,否则您可以忘记inline
并使用链接时优化。它消除了函数定义必须在头文件中才能考虑跨编译单元内联的要求,这正是inline
允许的。
(But see Is there any reason why not to use link time optimization?)
(但请参阅是否有任何理由不使用链接时间优化?)