std::bitset是 C++ 标准库中用于处理固定长度位序列的工具。你可以把它理解为一个长度在编译期就已确定的二进制数组,它既提供了类似数组的按位访问能力,又像整数一样支持整套位运算,同时还会将存储空间压缩到极致(理论上每个 bit 只占 1 bit 空间,无额外指针开销)。
核心特性速览
固定大小,编译期确定:大小
N是模板参数,必须在编译时是常量。一旦定义,长度不可改变。空间高效:标准要求以最紧凑的方式存储
N个位,没有动态内存分配。支持完整位运算:
&、|、^、~、<<、>>以及对应的复合赋值运算符&=、|=、^=、<<=、>>=全部可用。与字符串和整数互转:可以从
"1010"这样的字符串或整数构造,也能通过to_string、to_ulong、to_ullong转换回去。不是容器:它没有迭代器,也不能像
std::vector那样动态增删元素。如果需要运行时改变长度,应使用std::vector<bool>或boost::dynamic_bitset。
主要接口梳理
构造与初始化
| 方式 | 说明 |
|---|---|
bitset<N> b; | 全部位初始化为0 |
bitset<N> b(42ULL); | 用整数的二进制表示初始化右侧若干位,高位补0 |
bitset<N> b("1010"); | 用'0'/'1'字符串初始化(注意最右侧字符对应最低位b[0]) |
bitset<N> b(str, pos, n); | 从字符串的子串构造 |
元素访问与查询
| 成员函数 | 作用 |
|---|---|
b[i] | 返回第i位的代理引用,可读可写 |
b.test(i) | 返回第i位是否为1,带越界检查(越界抛出std::out_of_range) |
b.count() | 返回1的个数(C++23 起有constexpr优化) |
b.size() | 返回N |
b.all()/b.any()/b.none() | 全部为1/ 至少一个为1/ 全部为0 |
修改操作
| 操作 | 说明 |
|---|---|
b.set()/b.set(i) | 全部置1/ 第i位置1 |
b.reset()/b.reset(i) | 全部置0/ 第i位置0 |
b.flip()/b.flip(i) | 全部翻转 / 第i位翻转 |
位运算
std::bitset重载了所有标准位运算符,语义与整数位运算一致:
cpp
auto c = a & b; // 按位与 auto d = a | b; // 按位或 auto e = a ^ b; // 按位异或 auto f = ~a; // 按位取反 auto g = a << 3; // 左移(向高位移动) auto h = a >> 2; // 右移(向低位移动)
转换
b.to_string():返回"1010..."形式的字符串。b.to_ulong()/b.to_ullong():转换为无符号整数;如果N大于目标整数类型的位宽,且高位有1,会抛出std::overflow_error。
版本演进:C++23 与 C++26
C++23(P2417R2):将
std::bitset的绝大多数成员函数标记为constexpr,使其可以在编译期求值中使用。C++26(P2697R0):新增了接受
std::string_view的构造函数,并进一步统一了字符串接口。
#include <iostream> #include <bitset> #include <string> int main() { // 1. 从字符串构造(右侧字符是最低位 b[0]) std::bitset<8> a("10110011"); std::cout << "a = " << a << "\n"; // 10110011 // 2. 从整数构造 std::bitset<8> b(0b01011101); // 二进制字面量 C++14 std::cout << "b = " << b << "\n"; // 01011101 // 3. 查询 std::cout << "a[0] = " << a[0] << "\n"; // 1(最低位) std::cout << "a.test(6) = " << a.test(6) << "\n"; // 0 std::cout << "a.count() = " << a.count() << "\n"; // 5 // 4. 修改 a.set(0); // 最低位置 1(本来就是 1) a.reset(1); // 第 1 位清 0 a.flip(7); // 最高位翻转(1→0) std::cout << "a after modification = " << a << "\n"; // 5. 位运算 auto c = a & b; auto d = a | b; auto e = a ^ b; std::cout << "a & b = " << c << "\n"; std::cout << "a | b = " << d << "\n"; std::cout << "a ^ b = " << e << "\n"; std::cout << "~a = " << ~a << "\n"; // 6. 移位(注意方向:<< 向高位索引移动) std::cout << "a << 1 = " << (a << 1) << "\n"; std::cout << "a >> 2 = " << (a >> 2) << "\n"; // 7. 转换回字符串和整数 std::string s = a.to_string(); unsigned long ul = a.to_ulong(); std::cout << "a.to_string() = " << s << "\n"; std::cout << "a.to_ulong() = " << ul << "\n"; return 0; }