标头中定义的函数是否保证内联?

发布于 2024-08-23 15:22:41 字数 84 浏览 7 评论 0原文

如果我在标头中定义非成员函数,它是否始终由编译器内联,或者编译器是否根据其启发式进行选择?我知道 __inline 只是一个提示,它与标头中的函数相同吗?

If I define a non-member function in a header, will it always be inlined by the compiler, or does the compiler choose based on its heuristics? I know that __inline is just a hint, is it the same with functions in headers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

意中人 2024-08-30 15:22:41

请记住,包含标头中的内容与直接在源文件中键入内容没有什么不同。因此,对于编译器而言,位于标头中并没有什么区别;它从来不知道它在那里。

因此,当您在头文件中定义函数并将该头文件包含在文件中时,就好像您只是将函数直接键入到文件中一样。所以现在的问题是,“编译器是否选择基于启发式内联事物?”

答案是“这取决于编译器”。该标准不保证什么内容会内联或不内联。也就是说,任何现代编译器都将非常智能地了解其内联内容,可能会采用启发式方法。

然而,我们遇到了一个有趣的问题。想象一下,标头中有一个函数,并且您将该标头包含在多个源文件中。然后,您将在翻译单元中拥有该函数的多个定义,这违反了单一定义规则。因此,你会得到编译错误。 (链接器错误通常是这样的:“错误,函数 x 已在 y 中定义”)您可以做的是使用 inline 关键字,这样就不再违反 ODR。

顺便说一句 __inline 是非标准的。与您的帖子相反,它通常是一个编译器扩展,它强制内联,而不是暗示它。 inline 是标准关键字,最初是为了暗示内联。就像你说的,大多数现代编译器在这方面完全忽略它,现在它的唯一目的是提供内部链接。

Remember that including something from a header is no different than just typing it directly in the source file. So being in a header makes no difference as far as the compiler is concerned; it never knew it was there.

So when you define a function in a header file, and you include that header file in a file, it's like you just typed the function straight into the file. So now the question is, "does the compiler choose to inline things based on heuristics?"

The answer is "it depends on the compiler". The standard makes no guarantees about what gets inlined or not. That said, any modern compiler will be extremely intelligent about what it inlines, likely with heuristics.

However, we come to an interesting point. Imagine you have a function in a header and you include that header in multiple source files. You will then have multiple definitions of the function, across translation units, and this violates the one-definition rule. Ergo, you will get compile errors. (The linker error is usually something along the lines of: "Error, function x already defined in y") What you can do is use the inline keyword and you no longer violate the ODR.

By the way __inline is non-standard. Contrary to your post, it's usually a compiler extension which forces inlining, not hints it. inline is the standard keyword, which was originally intended to hint at inlining. Like you say, most modern compilers completely ignore it in that regard and it's only purpose nowadays is to give things internal linkage.

稚然 2024-08-30 15:22:41

来自 C++ FAQ Lite

无论你如何指定一个函数
作为内联,这是一个请求
允许编译器忽略:it
可能会内联展开部分、全部或不内联
对内联函数的调用。

From the C++ FAQ Lite:

No matter how you designate a function
as inline, it is a request that the
compiler is allowed to ignore: it
might inline-expand some, all, or none
of the calls to an inline function.

我不咬妳我踢妳 2024-08-30 15:22:41

它将根据启发式进行选择。确保将其显式声明为内联,否则如果将标头包含在多个编译单元中,则可能会出现重复符号链接错误。

It will choose based on heuristics. Make sure you declare it as inline explicitly otherwise you may get a duplicate symbol link error if you include the header in more than one compilation unit.

轻拂→两袖风尘 2024-08-30 15:22:41

如果您在头文件中定义一个具有外部链接的函数并将其包含到多个翻译单元中,您将收到编译错误(更准确地说:链接器错误),因为违反了单一定义规则(ODR) )。所以答案是“否”:在头文件中定义函数不会被编译器视为内联的提示,也不会成为您不遵守 ODR 要求的借口。不仅这样的函数不能保证被内联,而且很可能你的程序甚至无法编译。

为了在头文件中定义一个函数并摆脱它,你必须给它内部链接(声明它static,并最终在每个翻译单元中得到单独的函数),或者显式声明它内联

至于启发式......现代编译器通常会考虑几乎任何函数进行内联(通过应用启发式),无论它在哪里定义以及是否显式声明内联

If you define a function with external linkage in a header file and include it into more than one translation unit, you'll get compilation error (more precisely: linker erorr) for violation of One Definition Rule (ODR). So the answer is "no": defining a function in a header file will not be taken by compiler as a hint at inlining and will not excuse you from observing the requirements of ODR. Not only such functions are not guaranteed to be inlined, but most likely your program will not even compile.

In order to define a function in a header file and get away with it you have to either give it internal linkage (declare it static, and end up with separate function in each translation unit), or explicitly declare it inline.

As for the heuristics... Modern compilers will normally consider virtually any function for inlining (by applying heuristics), regardless of where it is defined and whether it is explicitly declared inline or not.

会发光的星星闪亮亮i 2024-08-30 15:22:41

标头中的函数没有什么魔力。编译器甚至不知道函数是否在标头中定义。 (由于标头实际上只是复制/粘贴到源文件中,因此您可以在标头中定义它,但编译器只是将其视为翻译单元的一部分)

“内联”还有两种不同的含义:

需要注意的 按照 C++ 标准的定义,函数可以内联:这可以通过在函数前面添加 inline 关键字来完成,或者如果它是成员函数,则可以通过在- 放置在类定义中。

这样做的效果是

  • 通知链接器它可能会遇到多个文件中的函数定义,它应该只是默默地将它们合并在一起而不是抛出错误,以便
  • 编译器更容易执行内联优化 >。

另一方面,内联优化只是用被调用函数的主体替换函数调用的行为,这意味着此优化实际上应用于调用站点,而不是函数。函数可能在某些地方被正常调用,但在其他地方被内联。当编译器认为函数调用是内联的时,最好在概念上将其与“内联”的第一个含义完全分开。

编译器将在需要时、何时何地应用内联优化。为此,它使用了很多启发式方法。较小的函数更有可能被内联。如果它确定特定的调用站点将被足够频繁地执行,则它更有可能被内联。最终,它使用的启发式方法基于“它会提高还是降低性能”。通常,它比人类能更好地判断这一点,因此您实际上不需要知道它使用了哪些精确的启发法。内联太多只会损害性能。

There is no magic about functions in headers. The compiler doesn't even know whether a function is defined in a header or not. (Since headers are effectively just copy/pasted into the source file, you might define it in a header, but the compiler just sees it as part of the translation unit)

There are also two different meanings of "inline" to be aware :

A function may be inlined as defined by the C++ standard: This is done either by prefixing the function with the inline keyword, or if it is a member function, by defining it in-place inside the class definition.

The effect of this is to

  • inform the linker that it may encounter the function definition in multiple files, and it should just silently merge them together instead of throwing an error
  • make it easier for the compiler to perform the inlining optimization.

The inlining optimization on the other hand, is simply the act of replacing a function call by the body of the called function, which means that this optimization is actually applied to call sites, not to functions. A function might be called normally some places, but inlined elsewhere. A function call is inlined when the compiler feels like it, and it is best to conceptually separate it entirely from the first meaning of "inline".

The compiler will apply the inlining optimization if, when and where it feels like it. It uses a lot of heuristics for this. Smaller functions are more likely to be inlined. If it determines that a specific call site is going to be executed sufficiently often, it is more likely to be inlined. Ultimately, the heuristics it uses are based on "will it improve or degrade performance". And it is generally a better judge of this than human beings, so you shouldn't really need to know what precise heuristics it uses. Inlining too much will only harm performance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文