繁体   English   中英

什么是聚合初始化

[英]what is aggregate initialization

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

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

为什么在 C 中容易出错且乏味? 聚合初始化是什么意思,为什么它更安全? 我在 Bruce Eckel 的“Thinking in C++” (第 2 版)中看到了“聚合初始化”一章,但它并没有让我相信任何事情。

首先,回答主要问题,聚合初始化意味着使用大括号括起来的初始化列表来初始化聚合的所有成员(即数组或结构[在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 中,数组是对象,因此它们的大小是已知的。 可以检查此大小,这可以保护开发人员在超出数组边界时访问不属于他/她的内存。

我觉得奇怪的是,在这种情况下甚至使用了“C++ 使用聚合初始化以使其更安全”的声明。

聚合初始化,这是大多数现代语言常见的,如下

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM