问题描述
一个有趣的问题是此处其他问题的副作用,它涉及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 ++是否会对未指定的值进行零初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!