Tre*_*ent 0 c++ arrays initialization
我非常确定内置类型的数组是单元化的,而UDT数组是默认初始化的.
int foo[5]; // will contain junk
Foo foo[5]; // will contain 5 Foo objects that are default initialized
无论数组是在堆栈还是堆上分配,都会发生这种情况.
但是,我发现很难找到这方面的权威来源.Bjarne说:
"数组和结构的成员是默认初始化的,取决于数组或结构是否是静态的",这并没有真正告诉我太多.
我也试图在标准中找到一些东西,但到目前为止没有任何结果.
有谁知道确认上述的权威来源?
ISO C++ 03具有权威性:
POD结构是一个聚合类,它没有非POD结构类型的非静态数据成员,非POD联合(或此类类型的数组)或引用,并且没有用户定义的副本赋值运算符,也没有用户定义的析构函数.类似地,POD-union是一个聚合联合,它没有非POD结构类型的非静态数据成员,非POD联合(或此类类型的数组)或引用,并且没有用户定义的副本赋值运算符并且没有用户定义的析构函数.POD类是POD结构或POD结合的类.
算术类型(3.9.1),枚举类型,指针类型和指向成员类型的指针(3.9.2)以及这些类型的cv限定版本(3.9.3)统称为标量类型.标量类型,POD结构类型,POD联合类型(第9节),此类型的数组和这些类型的cv限定版本(3.9.3)统称为POD类型.
零初始化T类型的对象意味着:
- 如果T是标量类型(3.9),则将对象设置为0(零)转换为T的值;
- 如果T是非联合类类型,则每个非静态数据成员和每个基类子对象都是零初始化的;
- 如果T是联合类型,则对象的第一个命名数据成员为零初始化;
- 如果T是数组类型,则每个元素都是零初始化的;
- 如果T是引用类型,则不执行初始化.
默认初始化T类型的对象意味着:
- 如果T是非POD类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,该对象被零初始化.
对值类型T的对象进行值初始化意味着:
- 如果T是具有用户声明的构造函数(12.1)的类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
- 如果T是没有用户声明的构造函数的非联合类类型,那么T的每个非静态数据成员和基类组件都是值初始化的;
- 如果T是数组类型,那么每个元素都是值初始化的;
- 否则,该对象被零初始化
在进行任何其他初始化之前,静态存储持续时间的每个对象应在程序启动时进行零初始化.[注意:在某些情况下,稍后会进行额外的初始化.]
初始值为空集括号的对象,即(),应进行值初始化.
如果没有为对象指定初始化程序,并且该对象是(可能是cv限定的)非POD类类型(或其数组),则该对象应默认初始化; 如果对象是const限定类型,则底层类类型应具有用户声明的默认构造函数.否则,如果没有为非静态对象指定初始化程序,则该对象及其子对象(如果有)具有不确定的初始值); 如果对象或其任何子对象是const限定类型,则程序格式错误.
对于您的示例,int绝对是POD类型(它是算术类型),因此int在没有初始化程序的情况下,本地或类型字段将具有不确定的值.因为Foo,这取决于它是如何定义的 - 粗略地说,如果它没有构造函数,并且它的所有成员都是POD类型,那么它本身就是一个POD类型,也不会发生初始化.否则,将调用默认构造函数.即使这样,这并不意味着成员被初始化 - 规则是递归的,因此非POD类型的POD成员将不会被初始化,除非该类型的构造函数专门执行该操作(在其初始化列表中).
在所有情况下,静态变量和字段都是零初始化的.请注意,这也适用于非POD - 意味着类型的静态变量保证(T)0在构造函数运行之前将所有字段递归设置为偶数.
默认初始化任何聚合POD类型的一个方便技巧是{}在初始化程序中使用- 请注意它适用于结构体和数组:
char s[10] = {}; // all elements default-initialized
Foo foo = {}; // all fields recursively default-initialized
Run Code Online (Sandbox Code Playgroud)