Are empty constructors always callable in C ++?

I have a general question, which may be a bit specific to the compiler. I'm interested in the conditions under which the constructor will be called. In particular, in release / assembly mode optimized for speed , will a constructor or an empty constructor always be called when creating an instance of an object?

class NoConstructor { int member; }; class EmptyConstructor { int member; }; class InitConstructor { InitConstructor() : member(3) {} int member; }; int main(int argc, _TCHAR* argv[]) { NoConstructor* nc = new NoConstructor(); //will this call the generated constructor? EmptyConstructor* ec = new EmptyConstructor(); //will this call the empty constructor? InitConstructor* ic = new InitConstructor(); //this will call the defined constructor EmptyConstructor* ecArray = new EmptyConstructor[100]; //is this any different? } 

I searched and spent many times looking through the generated assembly code in Visual Studio. However, in release builds it can be difficult to execute.

In short: Is the constructor always callable? If so, why?

I understand that this will be very dependent on the compiler, but, of course, there is a common position. Any examples / sources you can cite will be really appreciated.

+7
source share
5 answers

If in optimization mode, if your class or POD structure (has only POD types) and the constructor is not specified, any C ++ compiler of production quality not only misses the call to the constructor, but does not even generate it.

If your class has non-POD members that must be called by constructors, the compiler will generate a default constructor that calls member constructors. But even then - it will not initialize POD types. That is, if you do not explicitly initialize member , you may end up with garbage there.

All this can even become a fantasy if your compiler / linker has LTO.

Hope this helps! And first do your work on the program, then use the profiler to detect slow spots, and then optimize it. Premature optimization can not only make your code unreadable, but also unnecessary blood clots of your time, but it may also not help at all. You should know what to optimize first.

Here is the code parsing in your example (x86_64, gcc 4.4.5):

 main: subq $8, %rsp movl $4, %edi call _Znwm movl $4, %edi movl $0, (%rax) call _Znwm movl $4, %edi movl $0, (%rax) call _Znwm movl $400, %edi movl $3, (%rax) call _Znam xorl %eax, %eax addq $8, %rsp ret 

As you can see, no constructors exist at all. There are no classes at all, each object is only 4 bytes.

With MS compiler, YMMV. Therefore, you need to check the disassembly yourself. But the result should be similar.

Good luck

+5
source

Will the generated constructor constructor / empty constructor always be called when instantiating an object?

Not. If your class is the so-called "POD" (plain old data), then the constructor generated by the wont compiler should always be called.

In particular, it will not be called in the following two cases:

 struct Pod { int x; }; int main() { Pod pod; std::cout << pos.x << std::endl; // Value undefined. Pod pod2 = Pod(); // Explicit value initialization. Pod* pods = new Pod[10]; // Values of `pods` undefined. Pod* pods2 = new Pod[10](); // Explicit value initialization. } 

Conditions for when exactly the type of POD is somewhat more complicated. C ++ FAQs have a good breakdown .

+15
source

The constructor is logically called. In the generated code, if the constructor does nothing, there will be no instructions that can be traced back to the constructor if your compiler is not very bad at optimizing and inserting a call to the newly returned one.

+10
source

Certain types of classes or types are called POD "Plain Old Data" in C ++. These types will not have constructors.

The rules for POD are important enough for you to look at them, but in the end: only contains primitive data types and does not have specific constructors.

+1
source

Your sample is not very good, you missed the public keyword in the sample classes, and in addition, in your examples, force zero initialization by writing CLASS * class = new CLASS(); instead of CLASS * class = new CLASS; .

In the code you put, zero initialization will always be performed as required by the standard. You can call it whatever you want, but there will be code guaranteeing the rules of the standard.

If you asked without showing this inconsistent code sample, then the only right answer would be compiler specific .

0
source

All Articles