为什么编译器不会自动内联自由定义的函数?而是导致链接器错误

Why compiler doesn't automatically inline freely defined function ? Instead results in linker error

本文关键字:函数 错误 链接 定义 编译器 自由 为什么      更新时间:2023-10-16

示例:

// header.h
void foo ()  // function definition in the file
{
}
// file1.cpp
#include"header.h"
...
// file2.cpp
#include"header.h"
...

以上代码将导致链接器错误。假设编译器自动生成inline foo(),则不会出现任何链接器错误。

我的问题是从语言的角度。为什么编译器不自动将其设为inline?这会有什么不同吗?

换句话说,问题是:"如果编译器在定义的每个自由函数前面假设inline,可能会发生什么错误?">

页眉只是作为页眉文本的复制粘贴处理。编译器不知道你的代码在头文件中,而不是在源文件中,所以它必须对两者进行相同的处理,允许出现错误。语言指定了这一点。

答案是,基本上,C++标准要求它以这种方式运行,所以它确实这样做了。这是一个定义规则的一部分。

实际上,编译器必须生成链接器可见函数,以防您在其他地方实际使用它。例如,以下文件3.cpp必须工作:

void foo();
void call_foo() {
    foo();
}

并且为了使其工作,为foo()生成的代码必须可用于链接器。编译器一次只看一个翻译单元(.cpp文件,加上其中包含的所有内容(,所以它不知道它实际上生成了两次。的确如此。然后链接器捕获它。

这不会导致链接器错误。它可能会导致链接器错误,但不需要编译器来捕获该错误。

跨模块一致性完全是程序员的责任。C++编译器不需要能够看到,例如,您在两个具有不同类定义的不相关文件中使用了相同的类名。不管发生什么都是你的错。

一般来说,C++编译模型的许多明显奇怪的弱点都与这样一个事实有关,即必须可以通过一次只看一个模块(编译单元(来编译C++程序。需要Is来确保编译时间和空间不会因大型项目而激增。

It可以inline It(但如果不是static,它仍然必须单独具有该功能(,但您没有抓住要点。

编译器发现您用相同的签名定义了函数两次。它们可能会有所不同。所以在链接阶段,它会生成一个错误,让你知道发生了什么不好的事情

声明放在头void foo ();中,并在cpp文件的一个中实现该函数。

根据C的定义,在链接时自动内联的问题是,是否存在两个同名的不同函数。底层的二进制接口没有维护必要的元数据来解决此类冲突。再加上第三个源文件,它使用(但没有定义自己(具有这样一个名称的函数,它将不知道应该使用哪一个。

我怀疑可能有一些实验性的C编译器(或者更可能是类C编译器(可以做到这一点,但它们在某种程度上肯定会破坏兼容性。