初始化零数组

众所周知,标量数组缺少的初始值设定项默认为零。

int A[5]; // Entries remain uninitialized
int B[5]= { 0 }; // All entries set to zero

但是这(下)是保证的吗?

int C[5]= { }; // All entries set to zero
75624 次浏览

空括号初始化执行数组的聚合初始化: 这将导致 int元素的零初始化。

是的,我保证。

是的,根据 聚合初始化的规则,它是有保证的(数组 C的所有元素都将是 值初始化,也就是说,在本例中是从 零初始化0)。

(强调我的)

If the number of initializer clauses is less than the number of members and bases (since C++17) or 初始化器列表完全为空, the remaining members and bases (since C++17) are initialized by their default initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates).


附注:

int A[5]; // Entries remain uninitialized

“保持未初始化”可能不准确。对于 int A[5];A的所有元素都是 默认初始化。如果 A是静态或线程本地对象,则元素将是 零初始化0,否则什么也不做,它们将是不确定的值。

事实上,当你说 int A[5] = { 0 };的时候 你说: 初始化第一个元素为零。由于聚合初始化,所有其他位置都初始化为零。

这一行是使数组中充满零的真正原因: int A[5] = { };

这就是为什么如果您使用 int A[5] = { 1 };,您将只有初始化为1的第一个位置。

首先,让我们证明为什么下面数组 A 中的每个元素都应该为零

int A[5] = {0};

如何保证? 这涉及以下标准:

  1. 它是一个 聚合初始化,因为它是数组类型,其初始值设定项子句的数目小于成员的数目,第一个元素的复制初始化为0。

类定义中的每个直接公共基(自 C + + 17以来)数组元素或非静态类成员 按数组下标/外观的顺序排列都是初始化器列表中相应子句中的 拷贝初始化

  1. 数组中的其余元素将遵循聚合初始化规则,并执行值初始化

如果初始化器子句的数量小于成员和基数(因为 C + + 17)或初始化器列表是完全空的,其余的成员和基数(因为 C + + 17)是由它们的默认成员初始化器初始化,如果在类定义中提供,或者(因为 C + + 14)从空列表复制初始化,根据通常的列表初始化规则(执行 非类类型的值初始化和非聚合类与默认构造函数,聚合初始化)。如果引用类型的成员是这些剩余成员之一,则程序格式不正确。

  1. 根据 值初始化,左边的4个元素将例程进入“零初始化”过程

否则,对象为零初始化。

  1. 根据 零初始化,其余元素的类型是 int,这是一个定标器类型,所以左边的4个元素将被初始化为0

如果 T 是标量类型,则对象的初始值是显式转换为 T 的整数常数零。

  1. 所以 A 中的每个元素都应该是零

证据已经证明了!

最后,让我们证明为什么下面数组 B 中的每个元素都应该是零

int B[5] = {};

根据 值初始化,它是一种值初始化形式

在所有情况下,如果使用大括号{}的空对并且 T 是聚合类型,则执行聚合初始化而不是值初始化。

它将进入上聚合初始化 # 2,然后 B 数组中的每个元素应该为零。

证据已经证明了!