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然后你会出现不一致/无声的错误行为(而不是错误)一旦你发现