目标文件何时包含类代码?

问题描述 投票:0回答:5

我只是好奇这个问题,但在网上找不到答案。

假设我们有简单的标题:

// 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 都包含该类的代码吗?

c++ default-constructor object-files
5个回答
4
投票

从标准来看:如果你不写任何构造函数,将会为你提供一个默认构造函数,并且这个默认构造函数是 内联定义的,相当于一个空构造函数

T::T() {}

我很确定[编辑]你这样的内联构造函数实际上根本不会产生任何机器代码。


3
投票

是的,大概编译器必须在两个目标文件中生成代码,以防它们最终没有链接在一起。然后,当您将两个目标文件链接到可执行二进制文件时,链接器使用一个定义规则来选择一个版本并丢弃另一个版本。


3
投票

首先,这当然取决于编译器以及许多其他情况。

这里有 3 种常见场景。

  1. 默认构造函数已生成并包含在您的 First.obj 和 Second.obj 对象文件中,但是当您将它们链接在一起以生成可执行文件时,仅使用并包含其中一个。

  2. 构造函数在创建对象的任何地方都是内联的(通常仅适用于简单构造函数,编译器可以将内存清零的地方)

  3. 无需生成/调用默认构造函数。如果您在文件范围声明一个对象,并且该对象只需要将其内存初始化为零,则可能会发生这种情况 - 编译器可能只是将对象放置在程序启动时初始化为零的特殊区域中 - 并完全省略调用默认构造函数。


0
投票

默认构造函数只不过是为对象分配空间。因为它不是动态变量,所以内存已经在加载阶段分配,不需要更多代码。

更有趣的是,如果您实现一个复杂的构造函数并动态分配对象,会发生什么。
在这种情况下,两个 obj 文件都将具有构造函数代码。


0
投票

都不是。在 C 和 C++ 中,您可以多次声明某些内容,例如,该函数有代码,但它在其他地方。您只能定义一次,并且在定义它的位置,即在该 obj 文件中生成代码的位置。因此,您有三个 .cpp 文件和一个标头,第一个文件定义类,另外两个文件创建类的对象。其他两个文件的 obj 文件将不包含该类的任何代码,只有一些足以让链接器调用代码的信息是定义文件的 obj。

如果您在两个地方定义类,通过将方法定义隐式地放在多个文件中包含的标头中,链接器不会介意,因为定义是“相同的”,它们最初恰好出现在每个 obj 中,并且最终的应用程序将仅包含生成的默认函数之一。

您可以随时创建任意多个类的实例,并且方法代码永远不会被复制。它存在于一个地方,用于存放所有不同的文件、函数等,以便使用和创建该类的对象。

一些默认构造函数可能很聪明并且需要一些代码,例如 POD 结构的一些默认构造函数可能会完全优化并且不需要任何代码。尽管创建更多实例不会复制任何函数(包括构造函数),但情况总是如此。

© www.soinside.com 2019 - 2024. All rights reserved.