为什么结构中的POD在创建堆中的对象或堆栈中的临时对象时由隐式构造函数初始化? [英] Why is a POD in a struct zero-initialized by an implicit constructor when creating an object in the heap or a temporary object in the stack?

查看:239
本文介绍了为什么结构中的POD在创建堆中的对象或堆栈中的临时对象时由隐式构造函数初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标准和 C ++书说,类类型成员的默认构造函数由隐式生成的默认构造函数调用,但内置类型不会初始化。但是,在这个测试程序中,当在堆中分配对象或使用临时对象时,会得到意外的结果:

 #include< ; iostream> 


struct Container
{
int n;
};

int main()
{
Container c;
std :: cout<< [STACK] Num:<< c.n < std :: endl;

container * pc = new Container();
std :: cout<< [HEAP] Num:<< pc-> n< std :: endl;
delete pc;

容器tc = Container();
std :: cout<< [TEMP] Num:< tc.n < std :: endl;

}

我得到这个输出:

  [STACK] Num:-1079504552 
[HEAP] Num:0
[TEMP] code>

这是一些编译器特定的行为吗?我真的不想依赖这个,但我很想知道为什么会发生这种情况,特别是对于第三种情况。

解决方案

这是预期的行为。有两个概念,默认初始化和值初始化。如果你没有提到任何初始化器,对象是默认初始化,而如果你提到它,即使as()为默认构造函数,对象是值初始化。当构造函数定义时,两种情况都调用默认构造函数。但是对于内置类型,值初始化将内存置零,而默认初始化不会。



所以当你初始化:

 键入x; 

它会调用默认构造函数,如果提供了一个,但原始类型将未初始化。但是,当您提及初始化程序时,例如

 键入x = {}; //仅适用于没有构造函数的struct / class 
类型x = Type();
Type x {}; // C ++ 11 only

原始类型(或结构的原始成员)将为VALUE -initialized。



类似地:

  struct X {int x ; X(); }; 

如果定义构造函数

  X :: X(){} 

未初始化,但如果您定义构造函数

  X :: X():x(){} 

它将被初始化为VALUE。这也适用于 new ,因此

  new int; 

应提供未初始化的内存,但

  new int(); 

应该将内存初始化为零。
不幸的是语法:

 键入x();由于语法歧义和



不允许使用


$ b pre> 类型x = Type();

必须调用默认构造函数后跟复制构造函数



C ++ 11引入了新的语法,

  Type x {}; 

可用于这两种情况。如果你仍旧坚持使用旧的标准,这就是为什么有Boost.ValueInitialized,所以你可以正确初始化模板参数的实例。



更详细的讨论。 in Boost.ValueInitialized documentation


The standard and the C++ book say that the default constructor for class type members is called by the implicit generated default constructor, but built-in types are not initialized. However, in this test program I get unexpected results when allocating an object in the heap or when using a temporary object:

#include<iostream>


struct Container
{
    int n;
};

int main()
{
    Container c;
    std::cout << "[STACK] Num: " << c.n << std::endl;

    Container *pc = new Container();
    std::cout << "[HEAP]  Num: " << pc->n << std::endl;
    delete pc;

    Container tc = Container();
    std::cout << "[TEMP]  Num: " << tc.n << std::endl;

}

I get this output:

[STACK] Num: -1079504552
[HEAP]  Num: 0
[TEMP]  Num: 0

Is this some compiler specific behaviour? I don't really intend to rely on this, but I'm curious to know why this happens, specially for the third case.

解决方案

It's expected behaviour. There are two concepts, "default initialization" and "value initialization". If you don't mention any initializer, the object is "default initialized", while if you do mention it, even as () for default constructor, the object is "value initialized". When constructor is defined, both cases call default constructor. But for built-in types, "value initialization" zeroes the memory whereas "default initialization" does not.

So when you initialize:

Type x;

it will call default constructor if one is provided, but primitive types will be uninitialized. However when you mention an initializer, e.g.

Type x = {}; // only works for struct/class without constructor
Type x = Type();
Type x{}; // C++11 only

a primitive type (or primitive members of a structure) will be VALUE-initialized.

Similarly for:

struct X { int x; X(); };

if you define the constructor

X::X() {}

the x member will be uninitialized, but if you define the constructor

X::X() : x() {}

it will be VALUE-initialized. That applies to new as well, so

new int;

should give you uninitialized memory, but

new int();

should give you memory initialized to zero. Unfortunately the syntax:

Type x();

is not allowed due to grammar ambiguity and

Type x = Type();

is obliged to call default constructor followed by copy-constructor if they are both specified and non-inlineable.

C++11 introduces new syntax,

Type x{};

which is usable for both cases. If you are still stuck with older standard, that's why there is Boost.ValueInitialized, so you can properly initialize instance of template argument.

More detailed discussion can be found e.g. in Boost.ValueInitialized documentation.

这篇关于为什么结构中的POD在创建堆中的对象或堆栈中的临时对象时由隐式构造函数初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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