手动位字段的内存节省与 std::bitset
Memory Conservation with Manual Bit Fields vs. std::bitset
我正在学习位标志和使用位运算符手动创建位域。然后我遇到了位集,这似乎是一种更简单、更清晰的存储位域的方法。我理解使用位字段的价值,以尽量减少内存使用。但是,在测试 sizeof(bitset) 之后,我很难理解这是一种更好的方法。
考虑:
#include <bitset>
#include <iostream>
int main ()
{
// Using Bit Set, Size = 8 Bytes
const unsigned int i1 = 0;
const unsigned int i2 = 1;
std::bitset<8> mySet(0);
mySet.set(i1);
mySet.set(i2);
std::cout << sizeof(mySet) << std::endl;
// Manually managing bit flags
const unsigned char t1 = 1 << 0;
const unsigned char t2 = 1 << 1;
unsigned char bitField = 0;
bitField |= t1 | t2;
std::cout << sizeof(bitField) << std::endl;
return 0;
}
输出为:
mySet 是 8 个字节。 bitField 是 1 个字节。
如果需要最少的内存使用,我是否应该不使用 std::bitset?
为了尽可能减少内存占用,您不应使用 std::bitset
。它可能需要比 char
或 int
等有效大小的普通内置类型更多的内存。因此,它可能有内存开销,但多少取决于实现。
std::bitset
的一个主要优点是它使您摆脱了各种类型的依赖于硬件的实现。理论上,硬件可以使用任何类型的任何表示,只要它满足 C++ 标准中的某些要求即可。因此,当您依赖 unsigned char t1 = 1
在内存中成为 00000001
时,实际上并不能保证这一点。但是如果你创建一个 bitset 并正确地初始化它,它不会给你任何令人讨厌的惊喜。
关于 bitfiddling 的旁注:考虑到以这种方式摆弄位的陷阱,你真的可以证明这种容易出错的方法而不是使用 std::bitset
甚至类型 int
和 bool
?除非你的资源非常有限(例如 MCU / DSP 编程),否则我认为你做不到。
Those who play with bits will be bitten, and those who play with bytes will be bytten.
顺便说一句,你使用位运算符声明和操作的char bitField
是一个位域,但它不是位域的C++语言概念,它看起来像这样:
struct BitField{
unsigned char flag1 : 1, flag2 : 1, flag3 : 1;
}
笼统地说,它是一种数据结构,其数据成员被细分为单独的变量。在这种情况下,(大概)8 位的 unsigned char
用于创建三个 1 位变量(flag1
、flag2
和 flag3
)。它被明确细分,但归根结底,这只是 compiler-/language-assisted 与您上面所做的类似的小摆弄。你可以 read more about bit fields here.
我正在学习位标志和使用位运算符手动创建位域。然后我遇到了位集,这似乎是一种更简单、更清晰的存储位域的方法。我理解使用位字段的价值,以尽量减少内存使用。但是,在测试 sizeof(bitset) 之后,我很难理解这是一种更好的方法。
考虑:
#include <bitset>
#include <iostream>
int main ()
{
// Using Bit Set, Size = 8 Bytes
const unsigned int i1 = 0;
const unsigned int i2 = 1;
std::bitset<8> mySet(0);
mySet.set(i1);
mySet.set(i2);
std::cout << sizeof(mySet) << std::endl;
// Manually managing bit flags
const unsigned char t1 = 1 << 0;
const unsigned char t2 = 1 << 1;
unsigned char bitField = 0;
bitField |= t1 | t2;
std::cout << sizeof(bitField) << std::endl;
return 0;
}
输出为:
mySet 是 8 个字节。 bitField 是 1 个字节。
如果需要最少的内存使用,我是否应该不使用 std::bitset?
为了尽可能减少内存占用,您不应使用 std::bitset
。它可能需要比 char
或 int
等有效大小的普通内置类型更多的内存。因此,它可能有内存开销,但多少取决于实现。
std::bitset
的一个主要优点是它使您摆脱了各种类型的依赖于硬件的实现。理论上,硬件可以使用任何类型的任何表示,只要它满足 C++ 标准中的某些要求即可。因此,当您依赖 unsigned char t1 = 1
在内存中成为 00000001
时,实际上并不能保证这一点。但是如果你创建一个 bitset 并正确地初始化它,它不会给你任何令人讨厌的惊喜。
关于 bitfiddling 的旁注:考虑到以这种方式摆弄位的陷阱,你真的可以证明这种容易出错的方法而不是使用 std::bitset
甚至类型 int
和 bool
?除非你的资源非常有限(例如 MCU / DSP 编程),否则我认为你做不到。
Those who play with bits will be bitten, and those who play with bytes will be bytten.
顺便说一句,你使用位运算符声明和操作的char bitField
是一个位域,但它不是位域的C++语言概念,它看起来像这样:
struct BitField{
unsigned char flag1 : 1, flag2 : 1, flag3 : 1;
}
笼统地说,它是一种数据结构,其数据成员被细分为单独的变量。在这种情况下,(大概)8 位的 unsigned char
用于创建三个 1 位变量(flag1
、flag2
和 flag3
)。它被明确细分,但归根结底,这只是 compiler-/language-assisted 与您上面所做的类似的小摆弄。你可以 read more about bit fields here.