布尔值对位域的优点

mre*_*555 1 c++ boolean bit-fields

我工作的代码库很旧。虽然我们用 c++11 编译几乎所有东西。许多代码是多年前用c 编写的。在旧领域开发新课程时,我总是发现自己必须在匹配旧方法或采用更现代的方法之间做出选择。

在大多数情况下,我更喜欢尽可能坚持使用更现代的技术。然而,我经常看到的一个常见的旧做法是位域,我很难争论它的使用。我们传递了很多消息,很多时候,它们都充满了单个位值。以下面的例子为例:

class NewStructure
{
public:

    const bool getValue1() const
    {
        return value1;
    }

    void setValue1(const bool input)
    {
        value1 = input;
    }

private:
    bool value1;
    bool value2;
    bool value3;
    bool value4;
    bool value5;
    bool value6;
    bool value7;
    bool value8;
};

struct OldStructure
{
    const bool getValue1() const
    {
        return value1;
    }

    void setValue1(const bool input)
    {
        value1 = input;
    }

    unsigned char value1 : 1;
    unsigned char value2 : 1;
    unsigned char value3 : 1;
    unsigned char value4 : 1;
    unsigned char value5 : 1;
    unsigned char value6 : 1;
    unsigned char value7 : 1;
    unsigned char value8 : 1;
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,新结构的大小为 8 字节,旧结构的大小为 1。
我添加了一个“getter”和“setter”来说明从用户的角度来看,它们可以是相同的。我意识到也许您可以为下一个开发人员提供可读性的案例,但除此之外,是否有理由避免位字段?我知道填充字段会影响性能,但是因为这些都是字符,所以填充规则仍然存在。

Ser*_*eyA 6

使用位域时需要考虑几件事。这些是(重要性顺序取决于情况)

  • 表现

位域操作在设置或读取时会导致性能损失(与直接类型相比)。一个简单的代码生成示例显示了发出的额外指令:https : //gcc.godbolt.org/z/DpcErN然而,位域提供更紧凑的数据,这对缓存更友好,并且可以完全抵消额外操作的任何缺点. 了解真实性能影响的唯一方法是在真实用例中对实际应用程序进行基准测试。

  • ABI 互操作性

位域的字节序是实现定义的,因此两个编译器生成的相同结构的布局可能不同。

  • 可用性

位域没有引用绑定,您也不能获取它的地址。这可能会影响代码并使其不太清楚。