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