预C++ 20位字段零初始化

Nic*_*ick 6 c++ initialization language-lawyer bit-fields c++11

问题在下面的代码中,询问使用的值初始化语法是否意味着对于各个位字段成员是零初始化还是未初始化:

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; //  "
Run Code Online (Sandbox Code Playgroud)

以下是位域的复习:https://en.cppreference.com/w/cpp/language/bit_field

为具有许多位字段的结构创建归零构造函数通常使用遗留代码中的丑陋memset来完成,因为在构造函数初始化列表中使用value-init语法重复每个位域成员的名称会产生无法管理的代码.即使结构是用于良好测量的POD,也可以完成此操作.想要在C++ 11中尽可能消除这种情况(不幸的是,默认成员初始化语法不适用于位字段,直到C++ 20).C++ 11是否使用{} -init语法保证对此进行零初始化?

YSC*_*YSC 6

struct S {
   int a : 3;
   int b : 1;
};
Run Code Online (Sandbox Code Playgroud)

Per [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语法保证对此进行零初始化?

是.