Writing a Default Constructor Forces Zero-Initiali

2020-03-26 08:53发布

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));

3条回答
姐就是有狂的资本
2楼-- · 2020-03-26 09:30

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楼-- · 2020-03-26 09:30

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.

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2020-03-26 09:36

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

查看更多
登录 后发表回答