




std::bitset是编译期固定大小的位容器,不支持动态扩容,模板参数必须为常量表达式;支持字符串/整数初始化、安全成员函数访问、同尺寸位运算及to_string/to_ulong等转换,但越界访问和跨宽度运算是常见陷阱。
std::bitset 的大小必须在编译时作为模板参数指定,比如 std::bitset 表示 8 位固定容器。它不是 std::vector 那种运行时可变的结构,也不能用变量做模板实参:int n = 16; std::bitset 是非法的。
常见误用是想用它替代动态位集,结果编译失败。真需要运行时大小,请改用 std::vector 或第三方库(如 boost::dynamic_bitset)。
std::bitset{"1010"} → 值为 10(十进制)std::bitset{12} → 二进制 1100,高位补零bitset 不保证清零(取决于存储期)operator[] 或 test()/set()/reset()
operator[] 返回的是 std::bitset::reference,一个代理对象,支持赋值:b[3] = true;。但它不返回 bool&,所以不能取地址或绑定到 bool& 引用。
更安全、语义更清晰的操作是用成员函数:
b.test(i):返回 bool,检查第 i 位是否为 1(越界会抛 std::out_of_range)b.set(i):置第 i 位为 1;b.set(i, false) 置为 0b.reset(i):等价于 b.set(i, false)
b.flip(i):翻转第 i 位注意:所有带索引的成员函数都做边界检查(debug 模式下),而 operator[] 在 release 下通常不检查 —— 容易踩越界读写坑。
std::bitset 重载了 &、|、^、~、、>>,用法接近原生整数:
std::bitset<8> a{"10101010"};
std::bitset<8> b{"11001100"};
auto c = a & b; // "10001000"
auto d = ~a; // "01010101"
关键限制:参与二元运算的两个 bitset 必须模板参数完全一致,即 std::bitset 和 std::bitset 可算,但和 std::bitset 无法直接运算 —— 编译报错,没有隐式转换。
n >= size(),结果为全 0()或全 0(>>)
a & 0xFF 会失败;必须先转成整数:a.to_ulong() & 0xFF
to_ulong() 和 to_ullong() 将位模式解释为无符号整数。但如果位数超出目标类型能表示的范围(如 bitset 调用 to_ulong()),会抛 std::overflow_error。
更稳妥的方式:
to_
ulong();≤ 64 用 to_ullong()
to_string() 获取 std::string,再手动解析(但要注意高位在前,如 bitset{"1010"}.to_string() 得 "1010")to_string() 不会异常,但生成的字符串长度恒等于模板参数,含前导零反向构造也依赖字符串格式:只接受由 '0' 和 '1' 组成的字符串,且长度不能超过模板大小,否则构造失败(抛 std::invalid_argument)。
实际工程中,如果频繁需要进制转换或跨宽度操作,往往说明 bitset 不是最合适的数据结构 —— 这时候该考虑用 uint64_t 配合手写位操作,或者封装一层适配逻辑。