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
考虑具有多个布尔属性的 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