c+中{}和{0}之间的括号初始化差异+; 几年前,我读到,使用{}和{ 0 }来初始化POD的C++有一些细微的差别,其中可以在代码中引入悲观。 D3D11_TEXTURE2D_DESC dsd = {}; D3D11_TEXTURE2D_DESC dsd2 = { 0 }:

c+中{}和{0}之间的括号初始化差异+; 几年前,我读到,使用{}和{ 0 }来初始化POD的C++有一些细微的差别,其中可以在代码中引入悲观。 D3D11_TEXTURE2D_DESC dsd = {}; D3D11_TEXTURE2D_DESC dsd2 = { 0 }:,c++,c++11,compilation,C++,C++11,Compilation,虽然我知道{0}肯定是从c继承而来的,而且{}是在c++11中引入的,但在编译过程中,这两者都被转换为同一个memset()调用: 然而,两种大括号初始化样式中的一种在内存初始化未对齐的情况下做了一些事情,有人愿意告诉我们哪种样式更好以及为什么吗?这两个版本都是“在C++11中引入的”。大括号初始化“只是”调用构造函数的一种方式。例如,D3D11_TEXTURE2D_DESC dsd={}调用默认构造函数,而D3D11_TEXTURE2D_DESC dsd2={0}调用可以使用const int

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

然而,两种大括号初始化样式中的一种在内存初始化未对齐的情况下做了一些事情,有人愿意告诉我们哪种样式更好以及为什么吗?

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

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

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


好的,现在哪一个更好,当然取决于你想要达到的目标。如果您正在处理C
struct
s,我更喜欢第二个,因为您不会得到未初始化的值。但是请忘记任何关于
memset()
之类的假设。请看构造函数。

调用您引用的语法

如果初始值设定项子句的数量小于成员的数量或初始值设定项列表完全为空,则剩余的成员将被值初始化

由于POD的值初始化与零初始化相同,所以显示的两个语法之间没有区别


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

在进一步操作之前,请跳到godbolt,亲自看看这些操作的实际功能。请随意设置一个测试结构,而不是D3D11_TEXTURE2D_DESC。至少从C++03开始,
{}
的使用就一直存在。请查看此页面,如果要初始化的零比变量多,您将得到一个诊断。如果零更少,编译器会将其视为有足够的零来初始化所有成员。我投票将此问题视为离题,因为它需要根据广泛的提示和关联猜测您可能遇到的问题。不,至少从C++03开始,这两个版本都可用。OP谈论的是POD,所以即使语义早于C++11。好吧,C++11将它们更改为做一些新的事情(调用接受
初始值设定项列表的构造函数),但该语法在C++11之前就有行为OP指定他谈论的是POD初始化,所以构造函数不在图中。@aschepler我想,我已经讨论了这两个问题,因为我试图给出一个更全面的答案。聚合初始化实际上就是他所寻找的,但这并不等同于他的
memset()
调用。我很抱歉。知道这是POD类型有帮助吗?但是
{}
是默认聚合初始化,
{0}
是零聚合初始化。@Nikos没有“默认聚合初始化”或“零聚合初始化”之类的东西。给定一个聚合,这两个语法都是聚合初始化<代码>{}
没有任何成员的初始化器,因此所有成员都是值初始化的,而
{0}
有第一个成员的初始化器,该成员是从文本0复制初始化的,其余成员是值初始化的。从文本0开始的复制初始化和值初始化实际上都具有与零初始化相同的行为。“对于第一个成员”,我认为它适用于所有成员,不是吗
{0}
只是将
类中的所有内容初始化为
0
,不是吗?而
{}
只执行默认的初始化/构造。我错了吗?@Nikos
{0}
中的
0
是第一个成员的初始化器<代码>{0,0}
将初始化两个成员<代码>{1}
将第一个成员初始化为1。没有初始化器的其余成员都是值初始化的。对于基本类型,这是零初始化<代码>{}
没有任何成员的初始化器,因此所有成员都是值初始化的(对于基本类型,初始化为零)。
memset(&dsd, 0, sizeof(dsd));