在 c++ 中大括号 {} 和 {0} 之间的初始化差异
Brace initialization difference betweein {} and {0} in c++
几年前,我读到使用 {} 和 {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
,以及一些更多的限制,归结为 Cstruct
s,您还可以获得聚合初始化。这基本上是你对 C 的期望。无论如何,D3D11_TEXTURE2D_DESC dsd2 = { 0 };
并不等同于memset(&dsd, 0, sizeof(dsd));
,因为编译器可能会出于任何原因向类添加填充,当然,字段的类型可能会在其构造函数中实现完全不同的内容。
好的,现在哪一个更好,当然取决于你试图实现的目标。如果您正在处理 Cstruct
s,我更喜欢第二个,因为您不会获得未初始化的值。但请忘记任何关于memset()
或类似事情的假设。请改为查看构造函数。
- 在 Python 和 c++ 2d 数组初始化之间.这是怎麽?为什么呢?
- 不同的类或结构初始化方法之间的性能差异是什么?
- p_threads初始化中向量和数组之间的区别
- 这些初始化之间有什么区别?
- 模板流运算符重载错误:引用初始化无效,与basic_istream和basic_ifstream之间的差异有关
- 直接列表初始化和复制列表初始化之间的差异
- 使用 double 在 C++ 中初始化 int 之间的差异
- 如果值来自成员变量,则复制初始化和参考初始化之间的C 差异
- 如何以包装的方式初始化布局,从而减少布局之间的空间
- 为什么在初始化 C 和 C++ 之间的全局变量时会有这种差异?
- 无效指针和非初始化的指针之间的差异
- 各种初始化和构造之间的关系
- 这些在C 中初始化C数组的方式之间有区别吗?
- 结构和类之间的C 差异VS2015中的初始化
- 对象的动态数组 - 初始化方法之间的差异
- 均衡符号和初始化之间的时间和空间复杂性是否存在差异
- 显式强制转换、直接初始化和复制初始化之间的行为不同
- 分配列表和初始化器列表之间 C++11 缩小的差异
- 在 c++ 中大括号 {} 和 {0} 之间的初始化差异
- 这两个初始化之间有什么区别