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

C++ 为什么编译器不';自动内联自由定义函数?而是导致链接器错误,c++,function,inline,linker-errors,language-lawyer,C++,Function,Inline,Linker Errors,Language Lawyer,例如: // header.h void foo () // function definition in the file { } // file1.cpp #include"header.h" ... // file2.cpp #include"header.h" ... 以上代码将导致链接器错误。假设编译器自动生成inline foo(),则不会出现任何链接器错误 我的问题是关于语言的观点。为什么编译器不自动将其内联?这会有什么不同吗 换言之,问题是:“如果编译器在定义的每个自由函

例如:

// header.h
void foo ()  // function definition in the file
{
}

// file1.cpp
#include"header.h"
...

// file2.cpp
#include"header.h"
...
以上代码将导致链接器错误。假设编译器自动生成
inline foo()
,则不会出现任何链接器错误

我的问题是关于语言的观点。为什么编译器不自动将其
内联
?这会有什么不同吗


换言之,问题是:“如果编译器在定义的每个自由函数前面假定
内联
,可能会发生什么错误?”

头被视为头文本的复制粘贴。编译器不知道您的代码是在头文件中,而不是在源文件中,因此它必须对这两个文件进行相同的处理,从而允许出现错误。语言指定了这一点。

标题仅被视为标题文本的复制粘贴。编译器不知道您的代码是在头文件中,而不是在源文件中,因此它必须对这两个文件进行相同的处理,从而允许出现错误。语言指定这个。

嗯,答案是,基本上,C++标准要求它这样做,所以它确实如此。这是问题的一部分

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

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

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

嗯,答案是,基本上,C++标准要求它这样做,所以它确实如此。这是问题的一部分

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

void foo();
void call_foo() {
    foo();
}
为了使其工作,链接器必须可以使用为
foo()
生成的代码。编译器一次只查看一个翻译单元(
.cpp
文件,以及其中包含的所有内容),因此它无法知道它实际生成了两次。的确如此。然后链接器捕捉到它。

它可以
内联
它(但是如果它不是
静态的
,它仍然必须单独拥有该函数),但是你没有抓住要点

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

将声明放在标题
voidfoo()中,并在其中一个cpp文件中实现该函数。

它可以
内联
它(但如果它不是
静态的
,它仍然必须单独拥有该函数),但您没有抓住要点

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


将声明放在标题
voidfoo()中,并在其中一个cpp文件中实现该功能。

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

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


一般来说,C++编译模型中明显的一些弱点与一个事实有关,即必须只通过一次只看一个模块(编译单元)编译C++程序。是为了确保大型项目的编译时间和空间不会爆炸。

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

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

一般来说,C++编译模型中明显的一些弱点与一个事实有关,即必须只通过一次只看一个模块(编译单元)编译C++程序。需要确保大型项目的编译时间和空间不会爆炸。

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

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

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


我怀疑可能有一些实验性的C(或更可能是类似C的)编译器可以做到这一点,但它们几乎肯定会以某种方式破坏兼容性。

编译器在每个自由函数前面假设关键字
inline
如何?@iammilind然后你会出现不一致/无声的错误行为(而不是错误)一旦你发现