std::bitset模板参数是编译期常量位数,非字节数;初始化用整数时低位对齐、高位截断,字符串构造需全为'0''1';访问需用test/set/reset做边界检查,[]不检查越界。

bitset 初始化时要注意模板参数是位数,不是字节数或变量名
很多人误以为 std::bitset 表示“存 8 个字节”,其实它表示**固定长度为 8 位的位容器**,底层通常用 1 个 unsigned long 或更小类型实现(编译器优化)。初始化时传入的整数会被按二进制低位对齐填充,高位补零。
常见错误:用十进制大数初始化导致意外截断
std::bitset<4> b1(15); // 正确:15 -> 1111,刚好填满 4 位
std::bitset<4> b2(16); // 截断!16 的二进制是 10000 → 取低 4 位 = 0000
std::bitset<4> b3("1101"); // 正确:字符串构造,支持 0/1 字符
std::bitset<4> b4; // 默认全 0- 字符串构造必须全由
'0'和'1'组成,否则抛std::invalid_argument - 不能用
std::bitset这种方式直接赋值字面量(C++20 前不支持),得写成b = 0b1010; std::bitset(0b1010) - 模板参数
N必须是编译期常量,不能是变量
用 test()、set()、reset() 操作单一位,别直接用下标赋值
bitset 支持 [] 访问(返回 reference),但**不检查越界**——越界访问是未定义行为(UB),调试时可能看似正常,发布版崩溃。
安全做法始终用 test(pos) 查询、set(pos) 置 1、reset(pos) 置 0,它们会做范围检查(越界抛 std::out_of_range)。
立即学习“C++免费学习笔记(深入)”;
std::bitset<8> b("10100000");
b.set(0); // 第 0 位(最右)变 1 → 10100001
b.reset(7); // 第 7 位(最左)变 0 → 00100001
if (b.test(3)) { /* 检查第 3 位是否为 1 */ }-
set()不带参数时置全部位为 1;reset()不带参数时清零;flip()全翻转 -
pos是从右往左数的索引(0-based),即b[0]对应最低有效位(LSB) - 如果确定不会越界且追求极致性能(如内循环),可用
[],但务必确保pos
位运算符重载天然支持,但注意优先级和临时对象生命周期
std::bitset 重载了 &、|、^、~、、>>,用法接近内置整数,但有关键差异:
std::bitset<8> a("10101010"), b("11001100");
auto c = a & b; // OK:结果是 bitset<8>,值为 "10001000"
auto d = ~a; // OK:翻转所有位
auto e = a << 2; // OK:左移 2 位,高位丢弃,低位补 0 → "10101000"- 移位操作不循环,超出边界的位直接丢失(不像
rotate) - 复合赋值如
a &= b是原地修改,比a = a & b更高效(避免拷贝) - 注意运算符优先级:
a & b == c等价于a & (b == c),不是(a & b) == c—— 务必加括号 - 不要返回局部
bitset的引用(比如函数返回bitset),它会绑定到已销毁对象&
转字符串或整数时,size 超过目标类型宽度会出错
to_ulong() 和 to_ullong() 要求位数 ≤ 目标类型的位宽(如 unsigned long 通常是 32 或 64 位),否则抛 std::overflow_error。而 to_string() 总是安全的,但返回的是高位在前的字符串(符合人类阅读习惯)。
std::bitset<64> big("1111111100000000111111110000000011111111000000001111111100000000");
// auto x = big.to_ulong(); // 在 32 位系统上大概率 overflow
auto y = big.to_ullong(); // 安全(假设 unsigned long long ≥ 64 位)
auto s = big.to_string(); // 返回长度为 64 的 string,s[0] 是最高位-
to_string()结果不含前导空格或0b前缀,就是纯'0'/'1'序列 - 若需转为十六进制字符串,得自己分组处理(
bitset不提供直接支持) - 频繁转换建议缓存结果,因为
to_string()每次都分配新字符串
实际项目中,bitset 最容易被低估的是它的栈上固定大小特性——没有堆分配、无异常构造(除字符串构造)、零成本抽象。但一旦 size 需要运行时决定,就得切到 vector 或手动管理 uint32_t*,这时候边界检查和内存对齐就变成显式责任了。









