当我们初始化这样的阵列时 int a[5] = {0}, ,编译器制作所有5个元素0。

但是我想知道为什么编译器不初始化 int a[5]={1} 相似地?为什么不使所有5个元素1?为什么标准不要求它?这不是一个很棒的功能吗?不丢失吗?

同样,如果初始化器中的元素数小于数组的大小,则编译可以用初始化器中的最后一个元素初始化其余元素。方法, int a[5]={1,2,3} 等同于 int a[5]={1,2,3,3,3}. 。同样, int a[10]={1,2,3,0} 等同于 int a[10]={1,2,3,0,0,0,0,0,0,0};.

如果标准要求它,这不是一个很棒的功能吗?还是有什么充分的理由造成此丢失的功能?


还有一个叫做的东西 指定的初始化器 在C99中,它被使用:

指定的初始化器可以与常规初始化器结合使用,如以下示例:

int a[10] = {2, 4, [8]=9, 10}

在此示例中,a [0]初始化为2,a1 初始化为4,[2]至[7]的初始化为0,并且[9]初始化为10。

很有趣。但是,即使此功能也不在C ++中。

有帮助吗?

解决方案

我个人发现更多的“逻辑”(即简单)具有固定的默认初始化器,而不是仅用于数组的最后一个规则。这可能看起来“实用”(即有用),但在逻辑上更复杂。

也就是说,我认为您正在做一个 大的 试图将逻辑应用于C ++等语言的错误。

C ++是一种复杂的语言,其规则是长期进化历史的结果,其当前形式是许多人甚至正式委员会的工作的结果(仅最后一部分就可以解释 任何事物).

像C ++这样的语言不能通过逻辑来推断,必须像历史一样研究它。除非你 哈里·塞尔顿 实际上,您无法使用逻辑推理推断历史记录。

如果您尝试使用逻辑而不是学习,则在C ++的某些地方会遭受很多痛苦。仅举几个...

  • 为什么默认调度静态(即 错误的)?
  • 为什么没有零指针的关键字?
  • 为什么两个未签名的差异是未签名的?
  • 为什么签名和未签名之间的总和是未签名的?
  • 如果未签名表示“ z_ {2^n}“那么为什么尺寸未签名?
  • 为什么 std::string s; s=3.141592654; 完全有效的C ++吗?
  • 为什么在C ++ 0x中 i = i++ + 1; 是不确定的行为和 i = ++i + 1; 已验证?
  • 为什么 double x=3.14; int y(int(x)); 并不是说 y 会3岁吗?

其他提示

为什么不使所有5个元素1?

因为你误会了什么 {} 方法。 (实际上,在C ++中,更好的方法是 {} 而不是 {0})。语法 {0} 并不意味着您希望将汇总设置为零。相反,它说您希望将第一个元素零分配给指示变量(可以是C ++中的阵列或类类型)。因为聚集体通常比一个值零具有更多的字段 默认构造. 。内置或POD类型的默认值是将所有字段设置为零,因此您将整个聚合物有效地设置为零。

至于为什么特别考虑以下内容。根据当前标准,以下任何断言都不会失败:

struct abc
{
    char field1;
    int field2;
    char field3;
};

int main()
{
    abc example = {'a', static_cast<int>('b')};
    //All three asserts pass
    assert(example.field1 == 'a');
    assert(example.field2 == static_cast<int>('b'));
    assert(example.field3 == '\0');

    int example2[3] = {static_cast<int>('a'), 42};
    assert(example2[0] == static_cast<int>('a'));
    assert(example2[1] == 42);
    assert(example2[2] == 0);
}

您期望的价值 field3 在您建议的标准更改中?即使您将其定义为如上所述的聚合初始化器中的最后一个元素,它也将与现有代码的兼容性打破,该代码假设其余元素是默认构建的。


编辑: 只是意识到您的问题是通过数组来提出的 - 但是结构或数组的答案是相同的,因此确实没关系。

edit2: 为了使其与标准保持一致,对类/结构的引用已被下面的“汇总”代替,该范围涵盖了结构和阵列案例。

是的,他们 可以 已经这样做了,但是他们没有,现在改变这种行为为时已晚。 C和C ++背后的决定几乎是对性能和极简主义的思想做出的,因此我想,如果没有其他事情,也没有其他作用。

这样的功能并没有让我如此出色。这是一件非常简单的句法糖,我很少发现需要将类似的数组初始化为0的任何东西。

典型的运行时库提供了一项功能,可轻松初始化数据到0。总的来说,这是在特定的 部分 在可执行文件中,由编译器和链接器组织。在程序启动时,运行时启动代码使用类似 memset() 将所有初始数据清除到0。这意味着零字节不必存储在可执行文件内部。

相反的是,如果您将数据初始化为某物 以外 零,然后该数据的字节必须存储在可执行文件本身中,因为自动启动器的初始评估仅为零。

因此,如果您要声明一大批 char (说一个兆字节?) {0}, ,然后不会在该数组的可执行文件中存储字节。另一方面,如果您要使用它 {1} 根据您的计划, 1 字节必须存储在可执行文件中。通过更改初始评估列表中的一个字符,可执行文件的大小增加了兆字节。

我相信这样的计划会违反 至少令人惊讶的原则.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top