在 c++ 中大括号 {} 和 {0} 之间的初始化差异

Brace initialization difference betweein {} and {0} in c++

本文关键字:之间 初始化 c++      更新时间:2023-10-16

几年前,我读到使用 {} 和 {0} 来初始化 POD 在 c++ 中有一些微妙的差异,可能会在代码中引入悲观化。

D3D11_TEXTURE2D_DESC dsd = {};
D3D11_TEXTURE2D_DESC dsd2 = { 0 }:

虽然我知道{0}肯定是从 c 继承而来的东西,而 {} 是 c++11 中引入的东西,但两者都应该在编译过程中转换为相同的 memset() 调用:

memset(&dsd, 0, sizeof(dsd));

然而,两种大括号初始化样式中的一种做了一些内存初始化未对齐的事情,有没有人关心哪种样式更好,为什么?

您引用的语法称为聚合初始化。

如果初始值设定项

子句数小于成员数或初始值设定项列表完全为空,则其余成员为值初始化

由于 POD 的值初始化与零初始化相同,因此您显示的两种语法之间没有区别。

甚至在 C++11 之前就是这种情况 - 空的初始值设定项列表不是它引入的东西。自 C++11 以来,非 POD 也允许使用语法。聚合初始化现在是此新列表初始化的特例。

这两个版本都是"C++11中引入的东西"。大括号初始化"只是"调用构造函数的一种方式。例如D3D11_TEXTURE2D_DESC dsd = {};调用默认构造函数,而D3D11_TEXTURE2D_DESC dsd2 = { 0 };调用默认构造函数,可以使用const int作为唯一参数调用该构造函数。它们都不会转换为类似于memset(&dsd, 0, sizeof(dsd));的任何内容,除非您的构造函数之一这样做。

如果您有隐式声明的默认构造函数,它将简单地为该struct的每个元素调用默认构造函数。内置类型的默认构造函数不执行任何操作,因此内存不会设置为零。

对于那些没有定义构造函数而只有公共成员的struct,以及一些更多的限制,归结为 Cstructs,您还可以获得聚合初始化。这基本上是你对 C 的期望。无论如何,D3D11_TEXTURE2D_DESC dsd2 = { 0 };并不等同于memset(&dsd, 0, sizeof(dsd));,因为编译器可能会出于任何原因向类添加填充,当然,字段的类型可能会在其构造函数中实现完全不同的内容。

好的,现在哪一个更好,当然取决于你试图实现的目标。如果您正在处理 Cstructs,我更喜欢第二个,因为您不会获得未初始化的值。但请忘记任何关于memset()或类似事情的假设。请改为查看构造函数。