我只是好奇这个问题,但在网上找不到答案。
假设我们有简单的标题:
// SimpleHeader.h
class SimpleClass
{
int i;
}
众所周知,该类的默认构造函数是自动生成的。
现在我还有 2 个文件:
// First.cpp
#include <SimpleHeader.h>
// ...
SimpleClass a;
// ...
和
//Second.cpp
#include <SimpleHeader.h>
// ...
SimpleClass b;
// ...
First.obj 和 Second.obj 都包含该类的代码吗?
从标准来看:如果你不写任何构造函数,将会为你提供一个默认构造函数,并且这个默认构造函数是 内联定义的,相当于一个空构造函数
T::T() {}
。
我很确定[编辑]你这样的内联构造函数实际上根本不会产生任何机器代码。
是的,大概编译器必须在两个目标文件中生成代码,以防它们最终没有链接在一起。然后,当您将两个目标文件链接到可执行二进制文件时,链接器使用一个定义规则来选择一个版本并丢弃另一个版本。
首先,这当然取决于编译器以及许多其他情况。
这里有 3 种常见场景。
默认构造函数已生成并包含在您的 First.obj 和 Second.obj 对象文件中,但是当您将它们链接在一起以生成可执行文件时,仅使用并包含其中一个。
构造函数在创建对象的任何地方都是内联的(通常仅适用于简单构造函数,编译器可以将内存清零的地方)
无需生成/调用默认构造函数。如果您在文件范围声明一个对象,并且该对象只需要将其内存初始化为零,则可能会发生这种情况 - 编译器可能只是将对象放置在程序启动时初始化为零的特殊区域中 - 并完全省略调用默认构造函数。
默认构造函数只不过是为对象分配空间。因为它不是动态变量,所以内存已经在加载阶段分配,不需要更多代码。
更有趣的是,如果您实现一个复杂的构造函数并动态分配对象,会发生什么。
在这种情况下,两个 obj 文件都将具有构造函数代码。
都不是。在 C 和 C++ 中,您可以多次声明某些内容,例如,该函数有代码,但它在其他地方。您只能定义一次,并且在定义它的位置,即在该 obj 文件中生成代码的位置。因此,您有三个 .cpp 文件和一个标头,第一个文件定义类,另外两个文件创建类的对象。其他两个文件的 obj 文件将不包含该类的任何代码,只有一些足以让链接器调用代码的信息是定义文件的 obj。
如果您在两个地方定义类,通过将方法定义隐式地放在多个文件中包含的标头中,链接器不会介意,因为定义是“相同的”,它们最初恰好出现在每个 obj 中,并且最终的应用程序将仅包含生成的默认函数之一。
您可以随时创建任意多个类的实例,并且方法代码永远不会被复制。它存在于一个地方,用于存放所有不同的文件、函数等,以便使用和创建该类的对象。
一些默认构造函数可能很聪明并且需要一些代码,例如 POD 结构的一些默认构造函数可能会完全优化并且不需要任何代码。尽管创建更多实例不会复制任何函数(包括构造函数),但情况总是如此。