什么是聚合初始化

Thinking in Java, 2nd Edition Chapter 4, page 231 Array Initialization部分有这样的说法:

在C中初始化数组容易出错且乏味。 C ++使用聚合初始化使其更安全。 Java没有像C ++这样的“聚合”,因为Java中的所有东西都是对象。 它确实有数组,并且数组初始化支持这些数组。

为什么C中容易出错且乏味? 聚合初始化是什么意思,为什么它更安全? 我遇到过这个,但它并没有让我相信任何事情。

首先,回答主要问题,聚合初始化意味着使用大括号括起初始化列表来初始化聚合的所有成员(即数组或结构[在C ++中,只有某些类型的结构计为聚合])。

明显,

 int ar[] = { 1 , 2 }; 

比…更安全

 int ar[2]; ar[0] = 1; ar[1] = 2; 

因为后者为初始化各个元素的索引中的拼写错误和其他错误提供了充分的机会。

看看今天的C和C ++,我不清楚为什么作者区分C和C ++。 两种语言都支持数组的聚合初始化。

一种可能性是作者提到了C标准的旧版本。 值得注意的是,在ANSI C(C89)中,一个重要的限制应用于聚合初始化:所有初始化器必须是常量表达式:

 /* This is possible in C89: */ f(int i) { int ar[] = { 1 , 2 }; } /* But this is not (because i is not a constant expression): */ f(int i) { int ar[] = { i , i+1 }; } 

这是由于C89中的3.5.7(引自我在这里找到的草案):

具有静态存储持续时间的对象的初始值设定项中的所有表达式或具有聚合或联合类型的对象的初始化列表中的所有表达式都应为常量表达式。

这显然限制了聚合初始化的有用性(甚至在1989年,我相信许多编译器实现了扩展,以便为非常量表达式启用聚合初始化)。

C标准的后续版本没有这个限制,我相信C ++的标准化版本(从C ++ 98开始)从未有过这样的限制。

我只能推测,但也许这就是作者的想法?

我假设作者警告你C和C ++中缺乏强制执行大小限制。 在C和C ++中,数组衰减到指向其第一个元素的指针。 然后它使用指针算法来查找索引所引用的元素。 由于数组不是对象,并且编译器不会努力存储它们的大小,因此没有长度检查。 在java中,数组是对象,因此它们的大小是已知的。 可以检查此大小,这可以保护开发人员在超越arrays边界时访问不属于他/她的内存。

我发现奇怪的是,“C ++使用聚合初始化使其更安全”的陈述甚至在这种情况下使用。

聚合初始化(大多数现代语言通用)如下所示

 int intArray[3] = {1,2,3}; int int2DArray[2][2] = {{1,2}, {3,4}}; 

这种类型的初始化假定您事先知道数组的大小及其内容。 这种类型的初始化保护可防止一个人过度踩边界,并提供初始化具有设定值的数组。 也许在这种情况下,作者想到了一个开发人员,他声明了一个大小为5的静态C数组。然后这个开发人员创建一个循环来初始化它的内容,但是将数组的边界超过一个,写入不是他/的内存她的。