我知道编译器在 C++ 中合成的函数,例如默认构造函数、复制构造函数等都是隐式内联的,但我只是好奇为什么?
并且,如果这些函数需要执行的任务太复杂以至于不适合内联怎么办?
第一个问题是它的真正含义是inline
什么?这个问题的答案与实际的内联关系不大,更多的是与单一定义规则有关。当编译器为内联函数生成代码时,它会标记链接器的符号,以便知道在不同的翻译单元中具有相同的符号是可以的。
考虑到这一点,答案很简单。如果函数不是inline
并且编译器在两个不同的翻译单元中生成它们,那么将两个翻译单元链接在一起将导致违反程序员无法修复的单一定义规则。
关于函数没有真正内联时会发生什么,上面的答案似乎不够清楚。从第一段开始:
当编译器为内联函数生成代码时,它会标记链接器的符号,以便知道在不同的翻译单元中具有相同的符号是可以的。
编译器确实会在每个使用该函数的翻译单元中生成一个函数符号。然后链接器将使用该标记(弱符号)从程序中丢弃除一个定义之外的所有定义。在许多情况下,inline
即使函数代码实际上是内联的,编译器也会生成函数的外联定义。
这与将函数标记为static
(内部链接)不同,就像它被标记为内部链接一样,所有这些定义都将保留在最终的可执行文件中*
*有一些链接器能够找出不同的符号完全相同并且会删除重复项,因此它可能void f() { std::cout << "Hi\n"; }
与 void g() { std::cout << "Hi\n";合并 } . Linkers that do this can also fold all of the
static` 一起起作用,但这是标准要求之外的优化。