Writing a Default Constructor Forces Zero-Initialization?

左心房为你撑大大i 提交于 2019-12-01 08:41:57

问题


These are my class definitions:

class Foo{
    int _ent;
public:
    void printEnt() const{cout << _ent << ' ';}
};

class Bar{
    Foo _foo;
public:
    void printEnt() const{_foo.printEnt();}
};

And this is my test code:

char* buf = new char[sizeof(Foo) + sizeof(Foo) + sizeof(Bar)];

fill(buf, buf + sizeof(Foo) + sizeof(Foo) + sizeof(Bar), 'J');

cout << ((int*)buf)[0] << ' ' << ((int*)buf)[1] << ' ' << ((int*)buf)[2] << endl;

Foo* first = new (buf) Foo;
Foo* second = new (buf + sizeof(Foo)) Foo();
Bar* third = new (buf + sizeof(Foo) * 2) Bar;

first->printEnt(); second->printEnt(); third->printEnt();

My output is:

1246382666 1246382666 1246382666
1246382666 0 1246382666

But if I add a public default ctor to Foo: Foo() : _ent(0) {}

My output becomes:

1246382666 1246382666 1246382666
0 0 0

Is this correct behavior? Should adding my own default ctor remove the possibility of default initialization?

I'm running this code on gcc 4.8.1 if it matters. The results should be dependable because I'm running in debug and asserting: assert(sizeof(Foo) == sizeof(int) && sizeof(Bar) == sizeof(int));


回答1:


Once you provide a constructor for a type, it will always be invoked, both for default initialization and for value initialization. It's a fundamental principle of the language. So once you define Foo::Foo(), it will be called any time you construct a Foo; if there is a default constructor, it will be invoked, even in the case of default initialization. So the behavior you are seeing is correct.

EDIT:

Default initialization is explained §8.5/7, in particular:

To default-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor (12.1) for T is called [...]

In your case, you'll probably also want to look at how the compiler generates a default constructor if none is provided, §12.1/4; in particular, the generated default constructor invokes the default constructor of any base classes or members.

Value initialization is in §8.5/8. It is basically default initialization preceded by zero initialization, so that default initialization that doesn't do anything still finds everything zero initialized.

More fundamentally, however: in this case, a very fundamental principle of C++ is involved, dating to long before the first standard: if you provide a constructor for an object, it will be used. Without doing all sorts of strange pointer casts, it is impossible to get an object without it being properly constructed. The standard describes how this occurs, and covers a lot of other special cases, but the basic principle has been there from the start (and any proposal which would cause it not to be respected in the standard is bound to fail).




回答2:


Your question has been answered in the C++11 revision of the standard:

class Foo{
    int _ent=0;
public:

    // ...
};

If you then define your own default constructor, the member will still be initialized to its default value, even if your default constructor does not explicitly do so.




回答3:


When you provided a default constructor you no longer get the compiler generated one. Since your default constructor initializes the member to 0 the member will always be 0, this is especially true since the member is private and you have no way to change it.



来源:https://stackoverflow.com/questions/27505539/writing-a-default-constructor-forces-zero-initialization

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