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

时间:2014-12-16 13:16:06

标签: c++ initialization default default-constructor

这些是我的班级定义:

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

但如果我将public默认ctor添加到FooFoo() : _ent(0) {}

我的输出变为:

  

1246382666 1246382666 1246382666
  0 0 0

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

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

3 个答案:

答案 0 :(得分:3)

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

编辑:

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

  

默认初始化T类型的对象意味着:

     

- 如果T是(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(12.1)   [...]

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

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

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

答案 1 :(得分:1)

您的问题已在标准的C ++ 11修订版中得到解答:

class Foo{
    int _ent=0;
public:

    // ...
};

如果您随后定义了自己的默认构造函数,则该成员仍将初始化为其默认值,即使您的默认构造函数未明确执行此操作。

答案 2 :(得分:0)

当您提供默认构造函数时,您不再获得编译器生成的构造函数。由于您的默认构造函数将成员初始化为0,因此成员将始终为0,这尤其正确,因为该成员是私有的,您无法更改它。