std::vector不能当Bitmap用,因其是位压缩特化,operator[]返回临时对象导致取地址失败、迭代器解引用生命周期短、无data()接口、resize可能丢数据,且set/test需严格边界检查与位运算规范。
直接用
实现海量去重,大概率在上线后崩溃或静默出错——它不是位图容器,而是带陷阱的布尔代理包装器。
为什么
不能当 Bitmap 用
它底层是位压缩特化,
返回的是临时
,不是
;这意味着:
编译失败,无法取地址做原子操作或 SIMD 加载
迭代器解引用结果生命周期极短,开
后可能读到垃圾值
没有
接口,你拿不到原始字节数组,
、
、
全部失效
某些 STL 实现中,
触发隐式重新分配,导致已设位丢失
和
的边界校验必须显式写死
Bitmap 构造参数是「最大可接受输入值」,不是元素个数。比如
表示支持
,调用
就越界了。
构造时应分配
个
,而非模糊的
开头必须有
,不能依赖调用方过滤负数或超大值
必须双检:
调试期建议用
替代
,触发
位索引计算必须用位运算,别用除法和取模
热点路径里
和
会触发 x86 除法微码,比位运算慢一个数量级。
C知道
CSDN推出的一款AI技术问答工具
下载
立即学习
“
C++免费学习笔记(深入)
”;
字索引改用
,位偏移改用
(64 位)或
(8 位)
置位表达式必须带
后缀:
内存需对齐到 32 或 64 字节(用
或
),否则 AVX2 指令如
直接 SIGSEGV
负数、稀疏大值、字符串怎么喂到位图里
位图只认非负整数索引,原始数据几乎从不满足这个前提。
含负数?拆成两个位图:
存 ≥0 数,
存
的绝对值
值域已知偏移(如 UID ∈ [100000, 10999999])?插入前统一减去
,再喂给
64 位整数且稀疏?放弃全量位图,改用两级结构:高 12 位作桶号,低 20 位作桶内偏移,每个桶配
字符串?先过
转成
,再按上述规则归一化;但注意哈希冲突,严格去重要加 fallback 哈希表
最常被忽略的一点:位图本身不存数据,只存“存在性”。想导出所有去重后的值,必须扫描全部位空间——哪怕只设了 100 个 bit,也要遍历
次。真要高频遍历,得额外维护插入顺序列表,或者直接换
库。
std::vectorstd::vectoroperator[]std::vector::reference bool&&bitmap[i]-O2data()memsetmemcpy_mm256_load_si256resize()set()test()BitMap(100)0~99set(100)(max_val + 63) / 64uint64_tn / 64set(size_t i)if (i >= size_) return;test(size_t i)i 且位掩码命中,否则未初始化内存返回随机值std::vector::at(i / 64) []std::out_of_rangei / 64i % 64i >> 6i & 63i & 7ULLdata[i >> 6] |= (1ULL ,否则左移超过 31 位未定义aligned_allocalignas(64)_mm256_testc_si256pos_bitmapneg_bitmap-x100000BitMap(10900000)std::bitsetstd::hash<:string>()size_tsize_roaringbitmap