Typedefs,(二进制)代码复制和对象文件(Typedefs, (binary) Code duplication and Object File)

编程入门 行业动态 更新时间:2024-10-25 02:20:29
Typedefs,(二进制)代码复制和对象文件(Typedefs, (binary) Code duplication and Object File)

假设我编译了一个包含这段代码的源文件文件,

struct Point { int x; int y; }; struct Size { int x; int y; };

由于Point和Size完全相同(就其成员的内存布局而言),编译器是否会在目标文件中生成重复的代码(每个struct一个)? 这是我的第一个问题。


现在,让我们从源代码中删除struct Size ,然后使用typedef定义它,就像这样,

typedef Point Size;

编译现在会做什么? 它是否会重复代码(因为typedef不只是重命名,而不是更多)?


现在假设我们有一个这样的类模板:

template <int UnUsed> class ConcreteError : public BaseError { public: ConcreteError () :BaseError(), error_msg() {} ConcreteError (int errorCode, int osErrorCode, const std::string& errorMessage) :BaseError(errorCode, osErrorCode, errorMessage){} };

然后我们设置一些定义,像这样,

typedef ConcreteError<0> FileError; typedef ConcreteError<1> NetworkError; typedef ConcreteError<2> DatabaseError;

由于模板参数int UnUsed不用于类的实现(只是假设),所以看起来这种情况与具有完全相同的内存布局的多个类完全相同(类似于struct Point和struct Size ),目标文件中会有重复的代码吗?

如果我们这样做会怎样

typedef ConcreteError<0> FileError; typedef ConcreteError<0> NetworkError; typedef ConcreteError<0> DatabaseError;

这种情况是否更好,因为现在我们在typedef中使用相同的实例化类?

PS:这个类模板代码取自这里:

如何使用C ++中的模板编程从基类创建派生类?


实际上,我不知道编译器如何从源代码生成目标文件,以及它如何处理类名,它的成员,其他符号等等。 它如何处理typedef? 它有什么用呢,

typedef int ArrayInt[100];

ArrayInt是一个类型吗? 代码编译器在目标文件中为它创建了什么? 100存储在哪里?

Suppose I compile a source file file which contains this piece of code,

struct Point { int x; int y; }; struct Size { int x; int y; };

Since Point and Size is exactly same (in terms of memory layout of it's members), would the compiler generate duplicate code (one for each struct) in the object file? That is my first question.


Now, lets remove the struct Size from the source code, and define it using typedef instead, like this,

typedef Point Size;

What would the compile do now? Would it duplicate code (since typedef isn't just renaming, rather it's more than that)?


Now suppose we have a class template like this:

template <int UnUsed> class ConcreteError : public BaseError { public: ConcreteError () :BaseError(), error_msg() {} ConcreteError (int errorCode, int osErrorCode, const std::string& errorMessage) :BaseError(errorCode, osErrorCode, errorMessage){} };

And then we setup few definitions, like this,

typedef ConcreteError<0> FileError; typedef ConcreteError<1> NetworkError; typedef ConcreteError<2> DatabaseError;

Since the template parameter int UnUsed is not used in the implementation of class (just suppose that), so it seems that this situation is exactly same as multiple classes having exactly same memory layout (similar to the case of struct Point and struct Size), would there be duplicate code in the object file?

And what if we do like this,

typedef ConcreteError<0> FileError; typedef ConcreteError<0> NetworkError; typedef ConcreteError<0> DatabaseError;

Is this situation better, since now we're using same instantiated class in the typedefs?

PS: this class template code is taken from here :

How to create derived classes from a base class using template programming in C++?


Actually, I don't have any idea how compiler generates object file from source code, and how it handles class names, it's members, other symbols and all. How it handles typedefs? What does it do with this,

typedef int ArrayInt[100];

Is ArrayInt a new type here? What code compiler creates for it in the object file? Where is 100 stored?

最满意答案

示例中没有一行会在目标文件中生成任何代码。 或者,更确切地说,它根本不会生成任何数据。 我认为“代码”仅指处理器指令。

目标文件中的数据分为三个部分:代码,静态数据和常量数据。

除内联函数外,代码由实际函数定义(包含函数体,而不仅仅是声明)生成。 内联函数每次实际使用时都会生成代码。 模板函数在实例化时生成代码,但多个实例通常由编译器,链接器或两者优化为单个实例。

通过定义全局变量,静态成员变量(再次,实际定义而不仅仅是类中的声明)和静态局部变量来生成静态数据。 不能使用const修饰符声明变量以转到静态数据段。

常量数据由与静态数据相同类型的变量声明生成,但是使用const修饰符,加上浮点文字加上字符串文字以及可能更多的文字,具体取决于硬件平台。 操作系统实际上可能不允许对硬件级别的常量数据进行写访问,因此如果您尝试在那里编写内容,您的程序可能会因访问冲突或分段错误而崩溃。

我不是真正的低级别专家,所以我可能错过了一些东西,但我认为我对整体情况描述得很好。

除非我真的遗漏了某些内容,否则程序中的任何其他内容都不会在目标文件中生成任何数据,尤其是声明和类型定义。 这些由编译器在内部使用。 因此,当编译器看到结构定义时,它会记住它由两个32位整数组成。 当它找到一些使用该结构的真实代码时,它知道它必须生成适用于两个32位整数的代码,必须至少分配8个字节来存储它,依此类推。 但是所有这些信息都是在编译时内部使用的,并没有真正进入目标文件。 如果C ++有类似反射的东西,那将是另一个故事。

请注意,虽然定义了很多结构,但是不会向目标文件添加任何内容,它可能会增加编译器本身的内存使用量。 因此,您可能会说定义相同的内容会导致编译时的数据重复,但不会导致运行时。

No single line from your examples will generate any code in the object file. Or, more precisely, it won't generate any data at all. I think "code" means just processor instructions.

The data in an object file is divided into three segments: code, static data and constant data.

The code is generated by actual function definitions (with function body, not just declarations) except for inline functions. Inline functions generate code each time they are actually used. Template functions generate code when they are instantiated, but multiple instantiations are usually optimized into single instances by either compiler, linker or both.

The static data is generated by defining global variables, static member variables (again, actual definitions and not just declarations inside a class) and static local variables. A variable must not be declared with const modifier to go to the static data segment.

The constant data is generated by the same kinds of variable declarations as the static data, but with const modifiers, plus floating-point literals plus string literals plus maybe more literals depending on the hardware platform. An OS may actually disallow write access to constant data on hardware level so your program may crash with access violation or segmentation fault if you try to write something there.

I'm not really an expert on such low-level things so I might have missed something, but I think I described the overall picture pretty well.

Unless I have really missed something, nothing else in a program generates any data in the object file, especially declarations and type definitions. These are used internally by the compiler. So when the compiler sees a struct definition, it remembers that it consists of two 32-bit integers. When it finds some real code that uses that struct, it knows that it must generate code that works with two 32-bit integers, must allocate at least 8 bytes to store it and so on. But all this information is used internally at the compile time and doesn't really go into the object file. If C++ had something like reflection, it would be another story.

Note that while defining a lot of structs add nothing to your object file, it may increase memory usage by the compiler itself. So you may say that defining identical things leads to data duplication at compile time but not at run time.

更多推荐

本文发布于:2023-08-01 11:21:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1357739.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:对象   代码   文件   Typedefs   binary

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!