什么是聚合初始化

时间:2013-07-18 01:09:35

标签: c++

“Thinking in Java,2nd Edition”的第4章,第231页中的“数组初始化”部分有这样的说法:

  

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

为什么C中容易出错且乏味?聚合初始化是什么意思,为什么它更安全?我在Bruce Eckel的“用C ++思考”(第二版)中遇到了the chapter "Aggregate initialization",但它并没有让我相信任何事情。

2 个答案:

答案 0 :(得分:17)

首先,回答主要问题,聚合初始化意味着使用大括号括起初始化列表来初始化聚合的所有成员(即数组或结构[在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(引用我发现的here草案):

  

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

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

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

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

答案 1 :(得分:1)

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

我发现奇怪的是'C ++使用聚合初始化使其更安全'这句话甚至在这种情况下使用。

聚合初始化(大多数现代语言都很常见)如下

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

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