在汇总初始化过程中,C ++是否会对未指定的值进行零初始化? [英] Does C++ zero-initialise unspecified values during aggregate initialization?

查看:88
本文介绍了在汇总初始化过程中,C ++是否会对未指定的值进行零初始化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个有趣的问题是此处其他问题的副作用,它涉及C和C ++处理方式(非静态存储持续时间)之间的可能差异:

An interesting question arose as a side effect of some other question here, about the possible differences between how C and C++ handle (the non-static-storage-duration):

int arr[7] = {0};

有人指出,在C ++中,其他元素不能保证为零,但我不确定我是否同意。

Someone was stating that, in C++, the other elements were not guaranteed to be zero but I'm not sure I agree.

现在C11状态为 6.7.9初始化/ 19


初始化应以初始化程序列表的顺序进行,为特定子对象提供的每个初始化程序都将覆盖先前为同一子对象列出的所有初始化程序; 所有未明确初始化的子对象应与具有静态存储期限的对象隐式初始化。

这意味着 arr 的其他六个元素将被初始化为零(因为 static int x; 会将 x 初始化为零)。

This means that the other six elements of arr will be initilised to zero (since static int x; would initialise x to zero).

我不确定如果C ++也是如此。在C ++ 20标准中, 9.3.1聚合/ 3 指出:

I'm unsure if this is also the case for C++. In the C++20 standard, 9.3.1 Aggregates /3 states:


当聚合时由 9.3.4 中指定的初始值设定项列表初始化,初始值设定项列表的元素被用作集合元素的初始值设定项。聚合中显式初始化的元素确定如下:

When an aggregate is initialized by an initializer list as specified in 9.3.4, the elements of the initializer list are taken as initializers for the elements of the aggregate. The explicitly initialized elements of the aggregate are determined as follows:

(3.1)-(与指定的初始化程序列表和类无关的东西-pax)。

(3.1) — (irrelevant stuff to do with designated initialiser lists and classes - pax).

(3.2)—如果初始化列表是一个初始化列表,则聚合的显式初始化元素是聚合的前 n 个元素,其中 n 是初始化列表中元素的数量。

(3.2) — If the initializer list is an initializer-list, the explicitly initialized elements of the aggregate are the first n elements of the aggregate, where n is the number of elements in the initializer list.

然后 / 4 说明显式初始化的工作方式,而 / 5 处理非显式情况:

Then /4 states how the explicit initialisations work, and /5 handles the non-explicit cases:


对于非联盟聚合,不是显式初始化的元素的每个元素都按以下方式初始化:

For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:

(5.1)—如果该元素有一个默认的成员初始化程序(10.3),该元素从该初始化程序初始化。

(5.1) — If the element has a default member initializer (10.3), the element is initialized from that initializer.

(5.2)—否则,如果该元素不是引用,则从空的初始化程序列表(9.3.4)。

(5.2) — Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list (9.3.4).

(5.3)—否则,该程序格式不正确。

(5.3) — Otherwise, the program is ill-formed.

在我看来,我们的特殊情况包含在<$ c中$ c>(5.2),因此我们必须转到 9.3.4 来查看 int会发生什么初始化为空列表( {} )。这会经历很多情况,但我相信第一个匹配的是:

It appears to me that our particular case is covered by (5.2) so we have to go to 9.3.4 to see what happens to an int initialised with an empty list ({}). This goes through a lot of cases but I believe the first one that matches is:


(3.11)—否则,如果初始化列表没有元素,则

(3.11) — Otherwise, if the initializer list has no elements, the object is value-initialized.

然后,从 9.3初始化器/ 8


对类型为T的对象进行值初始化的意思是:

To value-initialize an object of type T means:

(8.1)—如果T是a(可能是cv限定的)类类型(第10条),没有默认构造函数(10.3.4)或用户提供或删除的默认构造函数,则对象被默认初始化;

(8.1) — if T is a (possibly cv-qualified) class type (Clause 10) with either no default constructor (10.3.4) or a default constructor that is user-provided or deleted, then the object is default-initialized;

(8.2) —如果T是(可能是cv限定的)类类型,而没有用户提供或删除的默认构造函数,则将该对象初始化为零,并检查默认初始化的语义约束,以及T是否具有非平凡的默认值构造函数,对象是默认初始化的;

(8.2) — if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

(8.3)—如果T是数组类型,则每个元素都将被值初始化;

(8.3) — if T is an array type, then each element is value-initialized;

(8.4)—否则,对象是零初始化的。

(8.4) — otherwise, the object is zero-initialized.

因此,它是 8.4 ,它似乎是控制子句,意思是C ++也会 将数组的非显式元素初始化为零。

Hence, it's 8.4 which seems to be the controlling clause, meaning C++ will also initialise the non-explicit elements of the array to zero.

我的推理正确吗? C ++在遇到 int arr [7] = {0}; 时,会将所有元素设置为零吗?

Is my reasoning correct? Will C++, on encountering int arr[7] = {0};, set all elements to zero?

推荐答案

是。 C ++通常保持与C的向后兼容性,从而允许您包含和使用C代码。考虑一下是否有一些遗留的C代码,它们会尝试像您描述的那样初始化数组:

Yes. C++ generally maintains backward compatibility with C, allowing you to include and use C code. Consider if you have some legacy C code, that attempts to initialize an array like you describe:

int arr [7] = {0};

如果C ++的工作方式有所不同,并且C程序(在C语言下有效)假定此数组初始化为零,则代码为如果包含在使用C ++编译器编译的C ++项目中,则很容易失败。

If C++ worked any differently, and the C program (validly, under C) assumed that this array is zero initialized, then the code is liable to fail if included in a C++ project compiled with a C++ compiler.

为了确认,我在x64 Windows上使用Cygwin g ++编译了此C ++程序:

Just to confirm, I compiled this C++ program using Cygwin g++ on x64 Windows:

int main() {
    int arr[7] = {0};
}

然后反汇编函数 main 在GDB中:

and then disassembled function main in GDB:

push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
callq  0x1004010d0 <__main>
movq   $0x0,-0x20(%rbp)
movq   $0x0,-0x18(%rbp)
movq   $0x0,-0x10(%rbp)
movl   $0x0,-0x8(%rbp)
mov    $0x0,%eax
add    $0x40,%rsp
pop    %rbp
retq

如您所见,该程序将3个qword和1个dword的零值移入堆栈。这是28个字节,即我系统上7个整数的大小。

As you can see, the program moves 3 qwords and 1 dword worth of zeros into the stack. That's 28 bytes, which is the size of 7 ints on my system.

这篇关于在汇总初始化过程中,C ++是否会对未指定的值进行零初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆