Pre C++20 位字段零初始化
Pre C++20 bit field zero-initialization
问题在下面的代码中,询问使用所示的值初始化语法是否意味着对各个位域成员进行零初始化或未初始化:
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 语法重复每个位字段成员的名称会产生难以管理的代码。即使结构是一个很好的 POD,也会这样做。如果可能的话,希望在 C++11 中消除它(不幸的是,默认成员初始化语法在 C++20 之前不可用于位字段)。 C++11 是否保证使用 {}-init 语法对此进行零初始化?
Does C++11 guarantee zero-initialization for this with {}-init syntax?
是的。
struct S {
int a : 3;
int b : 1;
};
根据 [dcl.init.aggr]/1
,S
是一个集合。
An aggregate is an array or a class ([class]) with
(1.1) no user-declared or inherited constructors ([class.ctor]),
(1.2) no private or protected non-static data members ([class.access]),
(1.3) no virtual functions ([class.virtual]), and
(1.4) no virtual, private, or protected base classes ([class.mi]).
[ Note: Aggregate initialization does not allow accessing protected and private base class' members or constructors. — end note ]
[dcl.init.aggr]
的其余部分定义了如何初始化聚合,没有提及位域;因此,它们按照与其他聚合 类.
相同的规则进行初始化
S s{}
的含义定义在[dcl.init.aggr]/5
:
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
...
(5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
那么,让我们看看[dcl.init.list]/3
... and it is huge! Checking point after point, we find [dcl.init.list]/3.11
:
(3.11) Otherwise, if the initializer list has no elements, the object is value-initialized.
对于标量类型,这意味着零初始化:)
Does C++11 guarantee zero-initialization for this with {}-init syntax?
是的。
如 your struct is an aggregate. When you initialize an aggregate with an empty initializer each member of the aggregate is then, per [dcl.init.aggr]/5.2、
中所述
Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
[dcl.init.list] 中的相关部分是 3.11
Otherwise, if the initializer list has no elements, the object is value-initialized.
[ Example:
int** pp {}; // initialized to null pointer
— end example ]
因此,每个元素都将被值初始化,并且值初始化的相关部分处于[dcl.init]/8.4状态
otherwise, the object is zero-initialized.
所以我们知道每个bitfeild都会在s2
中被初始化为零。
问题在下面的代码中,询问使用所示的值初始化语法是否意味着对各个位域成员进行零初始化或未初始化:
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 语法重复每个位字段成员的名称会产生难以管理的代码。即使结构是一个很好的 POD,也会这样做。如果可能的话,希望在 C++11 中消除它(不幸的是,默认成员初始化语法在 C++20 之前不可用于位字段)。 C++11 是否保证使用 {}-init 语法对此进行零初始化?
Does C++11 guarantee zero-initialization for this with {}-init syntax?
是的。
struct S {
int a : 3;
int b : 1;
};
根据 [dcl.init.aggr]/1
,S
是一个集合。
An aggregate is an array or a class ([class]) with
(1.1) no user-declared or inherited constructors ([class.ctor]),
(1.2) no private or protected non-static data members ([class.access]),
(1.3) no virtual functions ([class.virtual]), and
(1.4) no virtual, private, or protected base classes ([class.mi]).[ Note: Aggregate initialization does not allow accessing protected and private base class' members or constructors. — end note ]
[dcl.init.aggr]
的其余部分定义了如何初始化聚合,没有提及位域;因此,它们按照与其他聚合 类.
S s{}
的含义定义在[dcl.init.aggr]/5
:
For a non-union aggregate, each element that is not an explicitly initialized element is initialized as follows:
...
(5.2) Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
那么,让我们看看[dcl.init.list]/3
... and it is huge! Checking point after point, we find [dcl.init.list]/3.11
:
(3.11) Otherwise, if the initializer list has no elements, the object is value-initialized.
对于标量类型,这意味着零初始化:)
Does C++11 guarantee zero-initialization for this with {}-init syntax?
是的。
如
Otherwise, if the element is not a reference, the element is copy-initialized from an empty initializer list ([dcl.init.list]).
[dcl.init.list] 中的相关部分是 3.11
Otherwise, if the initializer list has no elements, the object is value-initialized. [ Example:
int** pp {}; // initialized to null pointer
— end example ]
因此,每个元素都将被值初始化,并且值初始化的相关部分处于[dcl.init]/8.4状态
otherwise, the object is zero-initialized.
所以我们知道每个bitfeild都会在s2
中被初始化为零。