c++ - Pre C++20 位域零初始化
问题描述
问题在下面的代码中,询问使用所示的值初始化语法是否意味着对各个位域成员进行零初始化或未初始化:
struct S { // S is POD
int a : 3;
int b : 1;
};
S s1;
S s2{};
s1.a; // uninitialized (ok, we understand this)
s1.b; // "
s2.a; // zero or junk?
s2.b; // "
这是位域的复习:https ://en.cppreference.com/w/cpp/language/bit_field
为具有许多位字段的结构创建归零构造函数通常是在遗留代码中使用丑陋的 memset 完成的,因为在构造函数初始化列表中使用 value-init 语法重复每个位字段成员的名称会产生难以管理的代码。即使结构是一个很好的衡量标准,也会这样做。如果可能的话,希望在 C++11 中消除这种情况(不幸的是,直到 C++20 之前,默认成员初始化语法才可用于位字段)。C++11 是否保证使用 {}-init 语法对此进行零初始化?
解决方案
C++11 是否保证使用 {}-init 语法对此进行零初始化?
是的。
struct S {
int a : 3;
int b : 1;
};
每[dcl.init.aggr]/1
,S
是一个聚合。
聚合是一个数组或一个类 ([class]),其中
(1.1) 没有用户声明或继承的构造函数 ([class.ctor]),
(1.2) 没有私有或受保护的非静态数据成员 ([class.access] ),
(1.3) 没有虚拟函数 ([class.virtual]),和
(1.4) 没有虚拟、私有或受保护的基类 ([class.mi])。[注意:聚合初始化不允许访问受保护和私有基类的成员或构造函数。——尾注]
其余部分[dcl.init.aggr]
定义了聚合是如何初始化的,没有提到位域;因此,它们按照与其他聚合类相同的规则进行初始化。
的含义S s{}
定义在[dcl.init.aggr]/5
:
对于非联合聚合,每个不是显式初始化元素的元素都按如下方式初始化:
...
(5.2) 否则,如果该元素不是引用,则从一个空的初始化列表复制初始化该元素([ dcl.init.list])。
所以,让我们看看[dcl.init.list]/3
......它是巨大的!逐点检查,我们发现[dcl.init.list]/3.11
:
(3.11) 否则,如果初始化列表没有元素,则对象被值初始化。
对于标量类型,这意味着零初始化:)
C++11 是否保证使用 {}-init 语法对此进行零初始化?
是的。
推荐阅读
- firebase - 我无法使用谷歌登录包构建 ios
- python - for循环中的“打开”是python中的安全方法吗?
- python-3.x - 在 python networkx 中创建与主图具有相同边样式/宽度的节点类型子图
- algorithm - 使用布尔数组对数组进行排序
- c++ - 为什么最后一个推回对象的字段到向量中会转移到向量的其他对象?
- spring - Spring Boot 应用程序我无法从 oracle 数据库中获取数据,它在邮递员中返回 []
- javascript - 如何通过 socket.io 将图像发送到服务器?
- firefox-addon-webextensions - 如何在控制台中访问由内容脚本创建的全局变量?
- javascript - 通过 JavaScript 保存后关闭模式对话框(表单窗口)?
- .net - 'Employee' 是一种类型,在给定的上下文中无效