【问题标题】:Pre C++20 bit field zero-initializationPre C++20 位域零初始化
【发布时间】:2019-01-30 01:10:54
【问题描述】:

问题在下面的代码中,询问使用所示的值初始化语法是否意味着对各个位域成员进行零初始化或未初始化:

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

【问题讨论】:

  • 收回唯一有用的评论,来自 NathanOliver:一半的答案是here
  • @SergeyA 如果多个编译器具有相同的特定行为,那么标准通常会保证这一点。这允许乐于助人的语言律师首先开始寻找保证行为的规则。这类似于分支预测。如果存在具有冲突行为的编译器,则帮助程序可以从不保证行为的猜测开始。在这种情况下,如果助手确实找到了保证一种行为的规则,那么助手就会知道值得考虑他们是否在解释一个模棱两可的规则。

标签: c++ c++11 initialization language-lawyer bit-fields


【解决方案1】:

C++11 是否保证使用 {}-init 语法对此进行零初始化?

是的。


struct S {
   int a : 3;
   int b : 1;
};

[dcl.init.aggr]/1S 是一个聚合。

聚合是一个数组或一个类([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 语法对此进行零初始化?

是的。

【讨论】:

    【解决方案2】:

    正如Is Aggregate Initialization of Bit-Fields Allowed? 中所讨论的,您的结构是一个聚合。当您使用空初始化程序初始化聚合时,聚合的每个成员都是,每个 [dcl.init.aggr]/5.2

    否则,如果元素不是引用,则从空的初始化列表 ([dcl.init.list]) 复制初始化该元素。

    [dcl.init.list] 中的相关部分是3.11

    否则,如果初始化列表没有元素,则对象被值初始化。 [ 示例:

    int** pp {};   // initialized to null pointer
    

    — 结束示例 ]

    因此,每个元素都将被初始化,并且相关部分的值初始化在[dcl.init]/8.4 状态

    否则,对象被零初始化。

    所以我们知道s2中的每个bitfeild都会被初始化为零。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-26
      • 2014-06-29
      • 1970-01-01
      • 2020-03-11
      • 2014-12-29
      • 1970-01-01
      • 2015-09-23
      相关资源
      最近更新 更多