C++中数组不能用花括号初始化

5
我是一名有用的助手,可以为您翻译文本。
我正在学习C++,遇到了以下奇怪的事情:
如果我按照书上的方法初始化数组
int my_array[5] = {10}

每个数组字段仍然被初始化为零,但应该是十。

如果我在循环中初始化它,它就能按预期工作。

发生了什么?我正在使用Ubuntu,并使用g++编译。


1
每个字段,还是第一个字段之后的每个字段? - Rob Kennedy
只有第一个元素将为10,其余为0。 - Praetorian
1
实际上,第一个元素是10(这是我检查数组内容时犯的错误)。 - Marko Kacanski
@MarkoKacanski:我可以保证第一个数组元素my_array[0]被初始化为10 - isekaijin
@MarkoKacanski:我不相信。第一个元素将是10,其余的都将是0。 - Ed S.
当您提供不足长度的初始化列表时,对于数组,它们会进行零填充,您可以手动提供其余部分或使用循环。 - RichardPlunkett
3个回答

11

你观察到的是正确的:根据标准,数组中剩余的项会被初始化为0。


是的,我看到这是正确的行为。我使用的教程说,通过使用array[5] = {0},您可以将所有内容初始化为零。我错误地认为它适用于所有值。 - Marko Kacanski
2
@MarkoKacanski 针对值为0的情况,该方法是最优的,因为编译器可以以任意顺序分配所有值为0,并且本质上进行自我优化。在增量for循环中执行相同操作要不那么优秀,因为您需要指定迭代器、顺序和所有元素的值。然而,这是初始化为非零值的唯一方法(据我所知)。(std::fill_n 内部工作方式相同) - Trojan
1
使用 = {0} 和使用 = {} 是一样的,让编译器隐式地为你初始化第一个元素。换句话说,当使用大括号时,你明确指定的任何值都将仅初始化该字段为特定值,然后任何未指定的字段将被零初始化。因此,如果省略第一个字段,编译器将简单地为您进行零初始化。 - Remy Lebeau
2
Marko,你书中所说的是真的,虽然如果仅此而已,它就会误导人。第一个元素初始化为零的原因与其余元素初始化为零的原因不同。你的书应该提到这个区别,也许可以通过使用像你在问题中引用的示例之一来说明。我曾经和你一样的假设。 - Rob Kennedy

7
C++03标准(假设您在Ubuntu系统上有旧版本的GCC)表示:
8.5.1/7
如果初始化列表中的成员比聚合体中的成员少,则未明确初始化的每个成员都应该进行值初始化(8.5)。
而数组是一个聚合体:
8.5.1/1
聚合体是一个数组或没有用户声明构造函数(12.1),没有私有或受保护非静态数据成员(第11条),没有基类(第10条)和没有虚函数(10.3)的类(第9条)。
至于什么是值初始化:
要对类型T的对象进行值初始化意味着:
- 如果T是具有用户声明构造函数(12.1)的类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化无效); - 否则,对象将进行零初始化 这就是类型为int的变量发生的事情。

那正是我想要发布的支持信息。你有标准副本还是查看一些在线资源? - Jarhmander

6
当使用小于数组长度的列表进行初始化时,只有指定的元素会按预期进行初始化;其余元素则会被初始化为0。
要初始化所有值,请使用循环或者如std::fill_n所示的函数。具体可以参考这里
std::fill_n(my_array, 5, 10); // array name, size, value

在内部,std::fill_n等价于一个循环。来自第一个链接:

template <class OutputIterator, class Size, class T>
    OutputIterator fill_n (OutputIterator first, Size n, const T& val)
{
    while (n>0) {
        *first = val;
        ++first; --n;
    }
    return first;     // since C++11
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接