编写默认构造函数强制执行零初始化? [英] Writing a Default Constructor Forces Zero-Initialization?

查看:119
本文介绍了编写默认构造函数强制执行零初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的类定义:

  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为 Foo Foo():_ent(0){}



我的输出变为:


1246382666 1246382666 1246382666

0 0 0


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



我在gcc 4.8.1上运行这个代码。结果应该是可靠的,因为我在调试和声明中运行: assert(sizeof(Foo)== sizeof(int)&& / code>

解决方案

一旦你提供了一个类型的构造函数,它总是被
调用,无论是对于默认初始化还是对于值
初始化。这是语言的一个基本原则。
所以一旦你定义 Foo :: Foo(),它会被调用任何时候你
构造一个 Foo ;如果有一个默认构造函数,它将被
调用,即使在默认初始化的情况下。所以你看到的
行为是正确的。



编辑:



8.5 / 7,特别是:


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



- 如果T是一个(可能是cv限定的)类类型(第9条),T的默认构造函数(12.1)叫做
[...]


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



值初始化在§8.5/ 8中。它基本上是默认
初始化之前的零初始化,所以默认
初始化,不做任何事情仍然发现所有的
零初始化。



然而,更基本的是:在这种情况下,C ++的一个非常基本的
原则涉及,早在第一个
标准之前:如果你为一个对象提供一个构造函数,将
。没有做各种奇怪的指针转换,它
是不可能得到一个对象没有正确的
构造。标准描述了这种情况,并涵盖了
a很多其他特殊情况,但基本原则是
从那里开始(和任何提案,这将导致它不是
被尊重该标准必然会失败)。


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

解决方案

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

这篇关于编写默认构造函数强制执行零初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆