Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 头文件中定义的函数是否保证内联?_C++_Inlining - Fatal编程技术网

C++ 头文件中定义的函数是否保证内联?

C++ 头文件中定义的函数是否保证内联?,c++,inlining,C++,Inlining,如果我在头文件中定义了一个非成员函数,它将始终由编译器内联,还是编译器根据其启发式进行选择?我知道uu inline只是一个提示,它与标题中的函数相同吗?它将根据启发式进行选择。确保将其明确声明为内联,否则,如果在多个编译单元中包含标头,则可能会出现重复的符号链接错误。请记住,包含标头中的内容与直接在源文件中键入没有什么不同。因此,就编译器而言,在头中没有区别;它从来不知道它在那里 因此,当您在头文件中定义一个函数,并将该头文件包含在文件中时,就像您直接在文件中键入函数一样。所以现在的问题是,“

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

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

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

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

答案是“这取决于编译器”。该标准不保证什么是内联的。这就是说,任何现代编译器都会非常智能地处理其内联内容,很可能是使用启发式

然而,我们得出了一个有趣的观点。假设您在头中有一个函数,并且您将该头包含在多个源文件中。然后,您将有多个跨翻译单元的函数定义,这违反了“一个定义”规则。因此,您将得到编译错误。(链接器错误通常是这样的:“error,函数x已经在y中定义了”)您可以做的是使用
inline
关键字,并且不再违反ODR

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

来自:

无论您如何指定函数 作为内联,它是 允许编译器忽略:它 可以内联展开部分、全部或无 对内联函数的调用

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

为了在头文件中定义一个函数并解决它,您必须给它内部链接(声明它为
静态
,并在每个翻译单元中以单独的函数结束),或者显式声明它为
内联


至于启发法。。。现代编译器通常会考虑任何内联函数(通过应用试探法),不管它是在哪里定义的,它是否被明确声明为“代码>内联< /代码>”。编译器甚至不知道函数是否在头中定义。(由于头文件实际上只是复制/粘贴到源文件中,您可以在头文件中定义它,但编译器只将其视为翻译单元的一部分)

“内联”还有两种不同的含义需要注意:

函数可以由C++标准定义:内联函数是通过用<代码>内联< /COD>关键字预先定义函数,或者如果它是成员函数,则通过在类定义内对其进行定义。p> 其效果是

  • 通知链接器,它可能会在多个文件中遇到函数定义,它应该将它们默默地合并在一起,而不是抛出错误
  • 使编译器更容易执行内联优化
另一方面,内联优化只是用被调用函数的主体替换函数调用的行为,这意味着这种优化实际上应用于调用站点,而不是函数。函数通常在某些地方调用,但在其他地方内联。当编译器喜欢函数调用时,函数调用是内联的,最好在概念上将其与“inline”的第一个含义完全分开


编译器将应用内联优化,如果,在什么时候,在什么地方。为此,它使用了很多启发式方法。较小的函数更有可能被内联。如果它确定某个特定的调用站点将足够频繁地执行,那么它更有可能是内联的。最终,它使用的启发式方法是基于“它会提高还是降低性能”。一般来说,它比人类更能判断这一点,所以你不需要知道它使用了什么样的精确启发法。内联太多只会损害性能。

对于像g++这样的现代编译器在其决策中使用的启发式方法有什么想法吗?i、 e.是否遵循“内联任何函数,其中函数体中的调用站点与字节的比率小于X”的原则?还是更微妙的事情?@Jeremy:我不知道,尽管你提到我现在很感兴趣。今晚我可以去看看。我怀疑这很复杂。@GMan:关于内部链接的部分是不正确的<代码>内联对链接没有影响。在C++中,声明为代码>函数内联的函数具有外部链接(除非明确声明“代码>静态< /代码>”,就像任何其他函数一样。用于内联函数的ODR特别允许在不同的翻译单元中使用多个定义,即使链接是外部的