C++ 如果位于头文件中的“重载”函数未标记为“inline”,则其代码编译到何处?

C++ 如果位于头文件中的“重载”函数未标记为“inline”,则其代码编译到何处?,c++,compiler-construction,compilation,inline,C++,Compiler Construction,Compilation,Inline,我已经知道,当我将一个成员函数的定义放入一个头文件并将该函数标记为内联时,该函数中的代码内联到从.cpp文件调用该函数的任何位置,因此当涉及到编译的二进制文件时,我知道函数代码的位置——在依赖它的任何.cpp文件的编译代码中。但是,如果我没有在头中用inline标记函数,并且函数体足够大,以至于编译器选择不内联,会发生什么呢?在静态/动态库的上下文中,函数的类所属,函数的代码编译到哪里?或者它根本就没有编译,函数代码的最终目的地是库客户端的编译.cpp?如果是后一种情况,函数的代码是否仍然是内联

我已经知道,当我将一个成员函数的定义放入一个头文件并将该函数标记为内联时,该函数中的代码内联到从.cpp文件调用该函数的任何位置,因此当涉及到编译的二进制文件时,我知道函数代码的位置——在依赖它的任何.cpp文件的编译代码中。但是,如果我没有在头中用inline标记函数,并且函数体足够大,以至于编译器选择不内联,会发生什么呢?在静态/动态库的上下文中,函数的类所属,函数的代码编译到哪里?或者它根本就没有编译,函数代码的最终目的地是库客户端的编译.cpp?如果是后一种情况,函数的代码是否仍然是内联的,即使我没有用inline标记它,因为它的代码太重了?最后,在这种情况下,MSVC编译器的行为与GCC的不同吗


当然,我意识到将我想要内联到.h文件或.inl文件中的成员函数和重函数放入.cpp文件将使事情变得非常清楚,但我确实希望避免破坏跨文件类的实现,这就是兴趣所在。

它被直接编译到包含标题的每个翻译单元中。如果存在多个这样的文件,则会违反“一个定义”规则并使程序格式不正确


如果您真的想将所有代码放在一个文件中,请将其放在头文件中,并将函数标记为内联。这只是一个建议,所以如果函数太大,编译器无论如何都不会内联它,它会像非内联函数一样被编译。但是请注意,这不是规范C++,因为它可以大大增加编译时间。通常的模式实际上是将接口头与实现源文件分开。如果编译器决定不内联函数,它将被写入包含头的每个翻译单元的已编译目标文件中,并且链接器需要从其中一个目标文件中选择一个实例,因为每个版本的代码都是相同的,所以扔掉剩下的部分。

它直接编译到包含标题的每个翻译单元中。如果存在多个这样的文件,则会违反“一个定义”规则并使程序格式不正确


如果您真的想将所有代码放在一个文件中,请将其放在头文件中,并将函数标记为内联。这只是一个建议,所以如果函数太大,编译器无论如何都不会内联它,它会像非内联函数一样被编译。但是请注意,这不是规范C++,因为它可以大大增加编译时间。通常的模式实际上是将接口头与实现源文件分开。如果编译器决定不内联函数,它将被写入包含头的每个翻译单元的已编译目标文件中,并且链接器将被要求从其中一个目标文件中选择一个实例,因为每个版本的代码都是相同的,所以丢弃其余的实例。

,内联只是对编译器的一个请求——仅此而已

此外,没有什么可以阻止您在头中声明独立的静态函数。在这一点上,相同的二进制代码会在源文件包含头文件的每个对象文件中复制

猜猜看-内联函数也会发生同样的情况:


就个人而言,我只喜欢看到类和结构定义、typedef、常量、函数原型。。。还有外人。。。在头文件中。

正如您所知,内联只是对编译器的一个请求,仅此而已

此外,没有什么可以阻止您在头中声明独立的静态函数。在这一点上,相同的二进制代码会在源文件包含头文件的每个对象文件中复制

猜猜看-内联函数也会发生同样的情况:

就个人而言,我只喜欢看到类和结构定义、typedef、常量、函数原型。。。还有外人。。。在头文件中。

当您将函数标记为内联时,您并不是强迫编译器在调用它的每个位置都内联它,您只是告诉它定义是内联的,它应该在不同的编译单元中预期重复的副本。对于包含头并调用函数的每个编译单元,实际代码将至少编译一次

如果您没有将其声明为内联,链接器应该抱怨函数的多个定义,即使这些定义相同。

当您将函数标记为内联时,您并不是在调用函数的每个位置强制编译器内联它,而是告诉它该定义是内联的 d它应该期望在不同的编译单元中有重复的副本。对于包含头并调用函数的每个编译单元,实际代码将至少编译一次


如果没有内联声明,链接器应该抱怨函数的多个定义,即使这些定义相同。

如果头文件具有适当的ifndef/define以防止重复包含,链接器会抱怨吗?@DesmondHume,include防护仅防止文件多次包含在同一.cpp中。他们不会阻止文件在每个.cpp中包含一次。因此,每个.cpp都可能包含函数的一个副本,编译后的二进制文件也可能包含该副本。当链接器合并二进制文件时,它会注意到重复的文件。注意:这不会阻止链接器跨编译单元删除重复的版本。如果头文件具有适当的ifndef/define以防止重复包含,链接器会抱怨吗?@DesmondHume,include防护仅防止文件多次包含在同一.cpp中。他们不会阻止文件在每个.cpp中包含一次。因此,每个.cpp都可能包含函数的一个副本,编译后的二进制文件也可能包含该副本。当链接器合并二进制文件时,它会注意到重复的文件。注意:这不会阻止链接器跨编译单元删除重复的版本。如果函数太大,编译器无论如何都不会内联它-太好了,这就是我的问题所在:这些函数的代码编译到哪里?如果函数太大,编译器无论如何都不会内联它-太好了,这就是我的问题所在:这些函数的代码编译到哪里?