我非常确定内置类型的数组是单元化的,而UDT数组是默认初始化的。
int foo[5]; // will contain junk
Foo foo[5]; // will contain 5 Foo objects that are default initialized
无论数组是在堆栈还是堆上分配,都会发生这种情况。
但是,我发现很难找到这方面的权威来源。 Bjarne说:
“数组和结构的成员是默认初始化或不是,取决于数组或结构是否是静态的”,这并没有真正告诉我太多。
我也试图在标准中找到一些东西,但到目前为止没有任何结果。
有谁知道确认上述内容的权威来源?
答案 0 :(得分:7)
ISO C ++ 03具有权威性:
POD-struct是一个聚合类,它没有非POD-struct类型的非静态数据成员,非POD-union(或此类型的数组)或引用,并且没有用户定义的副本分配运算符,没有用户定义的析构函数。类似地,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
答案 1 :(得分:1)
“数组和结构的成员是默认初始化或不是,取决于数组或结构是否为静态”
这是权威的,虽然它可以更清楚:
static
的数组和结构初始化为零。答案 2 :(得分:1)
它在C ++标准中说,在8.5.9中:
如果没有为a指定初始值设定项 对象,对象是(可能是 cv-qualified)非POD类类型(或 对象应该是 默认初始化;如果对象是 const限定类型, 基础类型应具有 用户声明的默认构造函数。 否则,如果没有初始化器 为非静态对象指定的 对象及其子对象(如果有) 具有不确定的初始值。