链接器实际上对多重定义的"内联"函数做了什么?

Kyl*_*and 7 c c++ linker inline

在C和C++中,inline具有外部链接的函数当然可以在链接时具有多个定义,假设这些定义都是(希望)相同的.(我当然是指使用inline链接规范声明的函数,而不是指编译器或链接时优化器实际内联的函数.)

那么,当遇到多个函数定义时,常见的链接器通常会什么?特别是:

  • 所有定义都包含在最终可执行文件或共享库中吗?
  • 函数的所有调用是否都针对相同的定义?
  • 一个或多个C和C++ ISO标准是否需要上述问题的答案,如果没有,大多数常见平台都做同样的事情吗?

PS是的,我知道C和C++是单独的语言,但它们都支持inline,并且它们的编译器输出通常可以通过相同的链接器(例如GCC ld)链接,所以我相信它们之间在这方面没有任何区别.

Pet*_*ker 5

如果函数实际上是内联的,那么就没有什么可链接的了。只有当编译器出于某种原因决定内联扩展函数时,它才必须生成函数的外联版本。如果编译器为多个翻译单元生成函数的外联版本,您最终会得到多个具有相同“内联”函数定义的目标文件。

外部定义被编译到目标文件中,并被标记,以便链接器不会在有多个该名称的定义时抱怨。如果有多个,链接器只需选择一个。通常是它看到的第一个,但这不是必需的,如果定义都相同,则无关紧要。这就是为什么对同一个内联函数有两个或多个不同定义是未定义行为的原因:没有规则可以选择哪个。任何事情都可能发生。


Ker*_* SB 3

链接器只需要弄清楚如何删除所有定义的重复项。当然,前提是任何函数定义都已发出;内联函数很可能是内联的。但是,如果您获取具有外部链接的内联函数的地址,您总是会得到相同的地址(参见 [dcl.fct.spec]/4)。

内联函数并不是唯一需要链接器支持的结构;模板是另一个,内联变量也是如此(在 C++17 中)。