Are empty constructors always called in C++?

末鹿安然 提交于 2019-12-21 12:17:46

问题


I have a general question, that may be a little compiler-specific. I'm interested in the conditions under which a constructor will be called. Specifically, in release mode/builds optimised for speed, will a compiler-generated or empty constructor always be called when you instantiate 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've done a lot of searching, and spent some time looking through the generated assembly code in Visual Studio. It can be difficult to follow in release builds though.

In summary: Is the constructor always called? If so, why?

I understand this will very much depend on the compiler, but surely there's a common stance. Any examples/sources you can cite would be really appreciated.


回答1:


When in optimizing mode, if your class or structure is POD (has only POD types) and constructor is not specified, any production quality C++ compiler will not only skip the call to a constructor but not even generate it.

If your class has non-POD members who's constructor(s) have to be called, compiler will generate default constructor that calls member's constructors. But even then - it will not initialize POD types. I.e. if you don't initialize member explicitly, you may end up with garbage there.

The whole thing can get even fancies if your compiler/linker has LTO.

Hope it helps! And make your program work first, then use a profiler to detect slow places, then optimize it. Premature optimization may not only make your code unreadable and waste tons of your time, but could also not help at all. You have to know what to optimize first.

Here is a disassembly for code 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, there are no constructors called at all. There are no classes at all, every object is just a 4 bytes integer.

With MS compiler, YMMV. So you have to check disassembly yourself. But result should be similar.

Good luck!




回答2:


will a compiler generated constructor/empty constructor always be called when you instantiate an object?

No. If your class is a so-called “POD” (plain old data) then the compiler-generated constructor won’t always be called.

Specifically, it won’t be called in the two following 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.
}

The conditions for when exactly a type is a POD are a bit tricky. The C++ FAQ has a nice breakdown.




回答3:


Logically, the constructor is called. In generated code, if the constructor does nothing, there will be no instructions that can be traced back to the constructor, unless your compiler is very very bad at optimizing and inserts a call to something that just returns.




回答4:


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

The rules for being a POD are important enough that you should look them up, but in summary: only contains primitive data types and has no defined constructors.




回答5:


Your sample isn't very good, you've missed the public keyword in sample classes and moreover in your examples force zero-initialization by writing CLASS * class = new CLASS(); instead of CLASS * class = new CLASS;.

In the code as you put it - zero-initialization will always be performed as it is required by the standard. You can call it as you want - but there WILL be code to guarantee the rules of the standard.

If you had asked without showing this controversial sample code - then the only correct answer would be - compiler specific.



来源:https://stackoverflow.com/questions/5097545/are-empty-constructors-always-called-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!