C++:是否可以在同一字节内压缩“bool”对象?

C++: Is it possible to condense `bool` objects within the same byte?

考虑具有多个布尔属性的 class

class A
{
  bool a;
  bool b;
  bool c;
  bool d;
  bool e;
  bool f;
};

虽然每个 bool 对象都可以用一位表示,但这里每个属性都需要一个字节(如果我没记错的话)。该对象将占用 6 个字节而不是 1 个字节(实际使用其中的 6 位)。原因是位不可寻址,只有字节可寻址。

为了稍微压缩内存,可以使用 vector<bool>bitset,然后通过索引访问属性。例如,可以将 get 函数写为

bool A::get_d() {data[3];}

理想情况下,我希望能够使用 InstanceOfA.d 直接访问属性。是否可以这样做,同时确保我的所有 6 bool 都被压缩在同一个字节中?

您可以使用 bitfields。适用于 Repl.it 的 gcc 版本 4.6.3。

#include <iostream>

struct Test 
{
  bool a:1;
  bool b:1;
  bool c:1;
  bool d:1;
  bool e:1;
  bool f:1;
  bool g:1;
  bool h:1;
  //bool i:1; //would increase size to 2 bytes.
};

int main()
{
  Test t;
  std::cout << sizeof(t) << std::endl;
  return 0;
}

如果你真的关心保存 space,你应该使用 bitset 而不是位字段。

您可以查看 this answer 进行全面比较,但本质上,由于是结构体,位字段会有一些开销,编译器可能会或可能不会实际将元素打包在一起以保存 space.

然而,Bitsets 是专门为优化 space 分配而设计的,并且还提供了一些专门用于 bit twiddling 的有用功能。

一个位集在逻辑上只是一个位数组,但打包保存 space。你可以这样使用它:

std::bitset<8> bacon;
bacon.set();    // 11111111
bacon.reset(1); // 11111101 Note: counts index from the right

std::bitset<4> fancy (std::string("1111"));
fancy[1] = 0;      // 1101 Note: counts index from the right
fancy.test(1) == 0 // true