When do object files contain code for class?
Asked Answered
S

5

8

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?

Sheathe answered 8/9, 2011 at 14:0 Comment(3)
Just a note to all the answers - I think the question here really is if the code for the default constructor will exists 1 place in the resulting executable, or 2 places (one for each of the 2 compilation units). Also, do imagine SimpleClass has complex members, instead if a pod, in which case it is more obvious that the default constructor needs to have a bit of code behind it.Frit
Exactly what I wanted to say! )Sheathe
There will be one instance for all methods, default or not, in a class or struct. The one exception is for compiler generated inlined methods, which are duplicated wherever used or convenient.Reichsmark
F
4

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.

Fuchsia answered 8/9, 2011 at 14:27 Comment(8)
I think this really explains the situation. If it is inline, than it's code is in both cpp files. This means that it should be in each obj file.Sheathe
Werolik: Yes, but also the body is empty, and so "its code" is most likely not going to be visible at all.Fuchsia
Yeah, I understand that. But in theory, (without any optimization) it should have been there.Sheathe
The constructor may well be too complex to be a candidate for the inlining optimization. Remember that the inline keyword, as well as implicit inline marking as here, are only suggestions for the optimizer.Pastelist
The default constructor needs to call the constructor of members. In this case it's just an int. Imagine you have class Foo { std::string a;}; Somewhere when you create an object of Foo , the compiler will generate code that calls the constructor of std::string. (Maybe the compiler actually inlines that call, maybe it does not)Frit
@Ben Voigt Remember that declaring something inline (even if it doesn't get inlined) also means that the linker is allowed to removed duplicate implementations under the ODR.Keats
@Mark B: Certainly the ODR is related to weak linking, but I wouldn't say "The linker uses the ODR to pick one version". Anyway, that's beside the point, Kerrek is claiming that no separate instance of the function exists, because it's only inlined, and that is not necessarily true.Pastelist
@Ben: You're right in principle. I edited the answer to refer only to the OP's situation: With a class like SimpleClass I doubt there'd be any code. For complicated objects there may of course be a complex constructor, even if it's generated by the compiler.Fuchsia
K
3

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.

Keats answered 8/9, 2011 at 14:26 Comment(0)
F
3

First of all, it certainly depends on the compiler, and many other circumstances.

Here's 3 common scenarios.

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

  2. The constructor is inlined everywhere you create an object (typically only for simple constructors, places where the compiler can just zero out the memory)

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

Frit answered 8/9, 2011 at 14:38 Comment(0)
M
0

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.

Midiron answered 8/9, 2011 at 14:4 Comment(5)
So, your answer is no, because you're saying neither object file will have code for the class?Quickstep
I can write the function, that creates object of class SimpleClass. This means calling the constructor in run-time. The question is - where is it's code.Sheathe
@Rob Kennedy: the answer is no, but only in that specific scenario.Midiron
@Werolik: Again, if only default constructor is used there is no code for it. Even if it's in a function, then it mean that when the function will be called more space will be allocate on the stuck. but you don't need a "code" for it.Midiron
@Roee: The default constructor will call the constructor for all subobjects (base classes and members). Defaulted doesn't imply trivial.Pastelist
M
0

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.

Mauritius answered 8/9, 2011 at 14:27 Comment(2)
All the code for the methods are in one place, if there is corresponding cpp file for the header. In my question there is only header, which is not compiled, but included in other cpp files.Sheathe
@Werolik: A compiler actually compiles a "Translation Unit", which is the result of including the content of header files into a single cpp file. Since a single header file can be included in multiple .cpp files, its contents are often compiled more than once.Ring

© 2022 - 2024 — McMap. All rights reserved.