c++classtypedefobject-files

Typedefs, (binary) Code duplication and Object File


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?


Solution

  • 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.