c++11 兼容的编译器是否总是忽略内联提示?

Do c++11-compatible compilers always ignore inline hints?

old answer on When should I write the keyword 'inline' for a function/method? 说:

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'.

这个答案是在 2009 年发布的,所以我想最终弄明白:

  1. 现代 c++11 兼容编译器是否总是 忽略用户指定的 inline 提示并仅自动执行此操作?
  2. inline 提示是否仅保留以提供向后兼容性?
  3. 如果不是1.那么这个答案不正确?
  1. 不,他们只是按照标准要求将其解释,但一些编译器可能仅此而已(根据 MSVC 根据 inline 关键字的存在选择的文档,以及 GCC 5.1.0决定时会考虑 inline 关键字)。
  2. 不,在 linking 时也需要内联来避免重复符号。

inline关键字确实有意义,但不是您所期望的意思。这并不意味着编译器 must/should/might 内联扩展函数,编译器可能会决定按照它认为合适的方式去做,无论您是否使用 inline

它的意思是您应该并且可以在使用它的每个编译单元中重复函数定义,而不会导致 linking 错误 - 与 static 关键字非常相似。

例如 GCC 4.7.2(它可能不是最先进的,但仍然是一个相当现代的编译器)似乎解释 inline 不超过标准规定的范围。如果禁用优化并且打开优化,它似乎不会内联函数,它似乎无论如何都会内联。唯一的区别是编译器在不同情况下如何处理 "outlined" 函数,内联它只是简单地丢弃它或以在 link 时避免重复符号的方式处理它。

C++11 编译器遵循与 C++03 或该语言的任何版本相同的内联提示。

但是,请注意 inline 关键字不是内联提示。提示看起来更像 __attribute__((always_inline)).

inline 关键字(或隐式内联状态,适用于模板等)表示函数是在 header 中定义的,因此链接器应该期望看到多个副本它在合并翻译单元(.cpp 文件)时。之所以这样命名,是因为定义必须可用才能内联函数,这意味着库中的函数需要 inline 才能实际内联。

  1. Do modern c++11-compatible compilers always ignore inline hints specified by user and do this only automatically?

C++11 在这里无关紧要,C++11 标准没有改变 inline 的语义,编译器优化在很大程度上独立于正在编译的语言版本。

  1. Do inline hints only stay to provide backward compatibility?

不,inline 不是提示,编译器也不会 "ignore" inline 因为如果它那样做,你会得到多个定义错误。编译器赋予 inline 关键字的含义并不是您似乎理解的含义。这不是提示。

如果编译器看不到函数定义,它就无法内联它(Link-Time优化改变了这一点,但 LTO 的使用还不是很广泛,而且大多数库不附带 LTO-enabled 允许 link-time 内联的二进制文件)。

您应该将 inline 读作 "this function definition appears inline in this file" 而不是 "calls to this function should be inlined"。

因此 inline 关键字对于允许编译器在多个文件中查看函数定义很有用,这意味着它 可能 通过以下方式优化调用内联它们。这并不一定会使它比同一翻译单元中定义的任何其他函数更有可能被内联。

对于从多个翻译单元调用的函数,在 headers 中定义函数并使它们成为 inline 是编译器内联它们的 必要条件 , 但它 不够 (因为编译器根据其他条件做出内联决定)。

这与向后兼容性无关,今天和 2009 年一样真实。