std::bitset
有一个to_string()
方法,用于序列化为基于char
的{{1}}和1
字符串。显然,这对于bitset中的每个位使用一个8位0
,使序列化表示比所需的时间长8倍。
我想将bitset存储在二进制表示中以节省空间。仅当我的bitset中少于32位时,char
方法才有意义。我有几百个
我不确定我是否想在对象(地址)本身上使用to_ulong()
/ memcpy()
,因为这假定对象是POD。
API似乎没有提供内部数组表示的句柄,我可以从中获取地址。
我还想选择从二进制表示中反序列化bitset。
我该怎么做?
答案 0 :(得分:7)
这是一种基于通过一次读/写一位明确创建std::vector<unsigned char>
的方法......
template<size_t N>
std::vector<unsigned char> bitset_to_bytes(const std::bitset<N>& bs)
{
std::vector<unsigned char> result((N + 7) >> 3);
for (int j=0; j<int(N); j++)
result[j>>3] |= (bs[j] << (j & 7));
return result;
}
template<size_t N>
std::bitset<N> bitset_from_bytes(const std::vector<unsigned char>& buf)
{
assert(buf.size() == ((N + 7) >> 3));
std::bitset<N> result;
for (int j=0; j<int(N); j++)
result[j] = ((buf[j>>3] >> (j & 7)) & 1);
return result;
}
请注意,要调用反序列化模板函数bitset_from_bytes
,必须在函数调用中指定位集大小N
,例如
std::bitset<N> bs1;
...
std::vector<unsigned char> buffer = bitset_to_bytes(bs1);
...
std::bitset<N> bs2 = bitset_from_bytes<N>(buffer);
如果你真的关心速度,一个可以获得某些东西的解决方案就是进行循环展开,这样就可以一次完成一个字节的打包,但更好的是编写你自己的bitset实现而不是隐藏内部二进制表示,而不是使用std::bitset
。
答案 1 :(得分:2)
正如gamedev.net上的人所建议的,可以尝试使用boost::dynamic_bitset,因为它允许访问比特包数据的内部表示。
答案 2 :(得分:1)
编辑:以下内容无法正常使用。显然,“二进制格式”实际上意味着“二进制的ASCII表示”。
您应该可以使用std::ostream
将其写入operator<<
。它说here:
[Bitsets]也可以直接插入并以二进制格式从流中提取。
答案 3 :(得分:1)
回答我自己的问题是为了完整。
显然,没有简单的和便携式方法。
为简单起见(虽然不是效率),我最终使用to_string
,然后从字符串的所有32位块(以及余数*)创建连续的32位位集,并使用{{1在每个上面将这些位收集到二进制缓冲区中
这种方法让STL本身有点笨拙,尽管它可能不是最有效的方法。
* 请注意,由于to_ulong
是总位数的模板,因此余数位集需要使用一些简单的模板元编程算法。 < / p>
答案 4 :(得分:0)
除了转换为字符串并执行自己的字符串序列化之外,我看不到一种明显的方法,该字符串将8个字符的块组合成一个序列化的字节。
编辑:最好是用operator[]
迭代所有位并手动序列化。
答案 5 :(得分:0)
这可能会对您有所帮助,这只是各种序列化类型的一个小例子。 我添加了位集和原始位值,可以像下面这样使用。
(所有示例在https://github.com/goblinhack/simple-c-plus-plus-serializer)
class BitsetClass {
public:
std::bitset<1> a;
std::bitset<2> b;
std::bitset<3> c;
unsigned int d:1; // need c++20 for default initializers for bitfields
unsigned int e:2;
unsigned int f:3;
BitsetClass(void) { d = 0; e = 0; f = 0; }
friend std::ostream& operator<<(std::ostream &out,
Bits<const class BitsetClass & > const m
{
out << bits(my.t.a);
out << bits(my.t.b);
out << bits(my.t.c);
std::bitset<6> s(my.t.d | my.t.e << 1 | my.t.f << 3);
out << bits(s);
return (out);
}
friend std::istream& operator>>(std::istream &in,
Bits<class BitsetClass &> my)
{
std::bitset<1> a;
in >> bits(a);
my.t.a = a;
in >> bits(my.t.b);
in >> bits(my.t.c);
std::bitset<6> s;
in >> bits(s);
unsigned long raw_bits = static_cast<unsigned long>(s.to_ulong());
my.t.d = raw_bits & 0b000001;
my.t.e = (raw_bits & 0b000110) >> 1;
my.t.f = (raw_bits & 0b111000) >> 3;
return (in);
}
};