目标文件何时包含类代码?
我只是好奇这个问题,但在网上找不到答案。
假设我们有简单的标头:
// 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 都包含该类的代码吗?
I was just curious about the question, but couldn't find the answer in the Internet.
Let's suppose we have simple header:
// SimpleHeader.h
class SimpleClass
{
int i;
}
As we know, the default constructor is automatically generated for this class.
Now I have 2 more files:
// First.cpp
#include <SimpleHeader.h>
// ...
SimpleClass a;
// ...
and
//Second.cpp
#include <SimpleHeader.h>
// ...
SimpleClass b;
// ...
Will both First.obj and Second.obj contain code for the class?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
根据标准:如果您不编写任何构造函数,则会为您提供一个默认构造函数,并且此默认构造函数是内联定义的,相当于一个空构造函数
T::T() {}.
我很确定[编辑]这样的内联构造函数实际上根本不会产生任何机器代码。
From the standard: If you do not write any constructors, a default constructor will be provided for you, and this default constructor is defined inline and equivalent to an empty constructor
T::T() {}
.I'm pretty sure that [edit]your thus inlined constructor will not actually result in any machine code at all.
是的,大概编译器必须在两个目标文件中生成代码,以防它们最终没有链接在一起。然后,当您将两个目标文件链接到可执行二进制文件时,链接器会使用一个定义规则来选择一个版本并丢弃另一个版本。
Yes, presumably the compiler has to generate the code in both object files in case they weren't linked together eventually. The linker then uses the one definition rule to pick one version and throw the other one away when you link the two object files together into an executable binary.
首先,这当然取决于编译器和许多其他情况。
以下是 3 种常见场景。
生成默认构造函数并将其包含在您的 First.obj 和 Second.obj 对象文件中,但是当您将它们链接在一起以生成可执行文件时,仅使用并包含其中一个。
构造函数在您创建对象的任何地方内联(通常仅适用于简单构造函数,编译器可以将内存归零的地方)
无需生成/调用默认构造函数。如果您在文件范围声明一个对象,并且该对象只需要将其内存初始化为零,则可能会发生这种情况 - 编译器可能只是将对象放置在程序启动时初始化为零的特殊区域中 - 并完全省略调用默认构造函数。
First of all, it certainly depends on the compiler, and many other circumstances.
Here's 3 common scenarios.
The default constructor is generated and included in each of your First.obj and Second.obj object files, but when you're linking them together to produce the executable, only one of them used and included.
The constructor is inlined everywhere you create an object (typically only for simple constructors, places where the compiler can just zero out the memory)
There's no need to generate/call a default constructor. This might happen if you declare an object at file scope and the object just needs to have its memory zero initalized - the compiler might just place the object in a special region that is zero initialized at program startup - and omit calling the default constructor entierly.
默认构造函数只不过是为对象分配空间。因为它不是动态变量,所以内存已经在加载阶段分配,不需要更多代码。
更有趣的是,如果您实现一个复杂的构造函数并动态分配对象,会发生什么。
在这种情况下,两个 obj 文件都将具有构造函数代码。
default constructor is not more than allocating space for the object. since it's not a dynamic vars there memory is already been allocated in the loader stage and no more code is needed.
More interesting would be what would happen if you implemented a complex constructor and dynamically allocate the objects.
In that case, both obj files will have the constructor code.
两者都不。在 C 和 C++ 中,您可以多次声明某些内容,例如,该函数有代码,但它在其他地方。您只能定义一次,并且在定义它的位置,即在该 obj 文件中生成代码的位置。因此,您有三个 .cpp 文件和一个标头,第一个文件定义类,另外两个文件创建类的对象。其他两个文件的 obj 文件将不包含该类的任何代码,仅包含一些足以让链接器调用代码的信息,即定义文件的 obj。
如果您在两个地方定义类,通过将方法定义隐式地放在多个文件中包含的标头中,链接器不会介意,因为定义是“相同的”,它们最初恰好出现在每个 obj 中,并且最终应用程序将仅包含生成的默认函数之一。
您始终可以根据需要创建任意多个类的实例,并且方法代码永远不会被复制。所有不同的文件、函数等都存在于一个位置,以便使用和创建该类的对象。
一些默认构造函数可能很聪明并且需要一些代码,例如 POD 结构的一些构造函数可能会完全优化并且不需要任何代码。尽管创建更多实例不会复制任何函数(包括构造函数),但情况总是如此。
Neither. In C and C++, you can declare something lots of times, saying, there is code for this function, but it's somewhere else. You can only define once, and in the place where you defined it, that's where the code is generated, in that obj file. So, you have three .cpp files, and one header, the first file defining the class, the other two making objects of it. The obj files for the other two files will not contain any code for the class, just some information which is sufficient for the linker to put in calls to the code is the defining file's obj.
If you define the class in two places, by putting method definitions implicitly in a header included in multiple files, the linker won't mind, because the definitions are 'the same', they just happen to appear in each obj initially, and the final application will only include one of the one default functions generated.
You can always make as many instances of a class as you like, and the method code is never copied. It exists in one place for all the different files, functions, and on so that use and make objects of that class.
Some default constructors may be clever and need some code, some for POD structs for example may be optimised out entirely and not need any code. It's always the case though that making more instances doesn't copy any functions, including constructors.