是否会对未指定的值进行零初始化

是否会对未指定的值进行零初始化

本文介绍了在汇总初始化过程中,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:

(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:

(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:

然后,从 9.3初始化器/ 8

(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 ++是否会对未指定的值进行零初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 16:04