其他分享
首页 > 其他分享> > c – 编写默认构造函数强制进行零初始化?

c – 编写默认构造函数强制进行零初始化?

作者:互联网

这些是我的类定义:

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

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

这是我的测试代码:

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

我的输出是:

1246382666 1246382666 1246382666
1246382666 0 1246382666

但是如果我将一个公共默认ctor添加到Foo:Foo():_ent(0){}

我的输出成为:

1246382666 1246382666 1246382666
0 0 0

这是正确的行为吗?应该添加我自己的默认ctor删除默认初始化的可能性?

如果重要的话,我在gcc 4.8.1上运行此代码.结果应该是可靠的,因为我在调试和断言中运行:assert(sizeof(Foo)== sizeof(int)&& sizeof(Bar)== sizeof(int));

解决方法:

一旦为类型提供构造函数,它将永远是
调用,用于默认初始化和值
初始化.这是该语言的基本原则.
所以一旦你定义了Foo :: Foo(),它就会随时被调用
构建一个Foo;如果有默认构造函数,它将是
即使在默认初始化的情况下也会调用.所以
你看到的行为是正确的.

编辑:

默认初始化解释§8.5/ 7,特别是:

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
[…]

在你的情况下,你可能也想看看如何
如果没有提供,编译器会生成默认构造函数,
§12.1/ 4;特别是生成的默认构造函数
调用任何基类或成员的默认构造函数.

值初始化在§8.5/ 8中.它基本上是默认的
初始化之前是零初始化,因此默认
没有做任何事情的初始化仍会找到所有内容
零初始化.

然而,更根本的是:在这种情况下,非常根本
涉及C的原则,可以追溯到第一个之前很久
标准:如果您为对象提供构造函数,它将会
使用.没有做各种奇怪的指针演员,它
如果没有正确的话,就不可能得到一个物体
建.该标准描述了这种情况的发生和覆盖
很多其他特殊情况,但基本原则已经
从一开始(以及任何会导致它的提案)
在标准中受到尊重必然会失败).

标签:c,initialization,default,default-constructor
来源: https://codeday.me/bug/20191008/1872707.html