从bitset<64>
:
uint64_t
很容易
uint64_t flags = ...;
std::bitset<64> bs{flags};
但是有一种很好的方法可以从bitset<64 * N>
构建uint64_t[N]
,这样flags[0]
会引用最低的64位吗?
uint64_t flags[3];
// ... some assignments
std::bitset<192> bs{flags}; // this very unhelpfully compiles
// yet is totally invalid
或者我不得不在循环中呼叫set()
?
答案 0 :(得分:9)
std::bitset
没有范围构造函数,因此您必须循环,但使用std::bitset::set()
单独设置每个位是不完整的。 std::bitset
支持二元运算符,因此您至少可以批量设置64位:
std::bitset<192> bs;
for(int i = 2; i >= 0; --i) {
bs <<= 64;
bs |= flags[i];
}
更新:在评论中,@ icando提出了有效的担忧,即位移是std::bitset
的O(N)操作。对于非常大的位集,这最终会影响批量处理的性能提升。在我的基准测试中,std::bitset<N * 64>
的收支平衡点与单独设置位且不会改变输入数据的简单循环相比:
int pos = 0;
for(auto f : flags) {
for(int b = 0; b < 64; ++b) {
bs.set(pos++, f >> b & 1);
}
}
在N == 200
左右(x86-64上的gcc 4.9,libstdc ++和-O2
)。 Clang的表现稍差,甚至在N == 160
左右。带有-O3
的Gcc会将其推送到N == 250
。
采用低端,这意味着如果你想使用10000位或更大的位集,这种方法可能不适合你。在32位平台上(例如常见的ARM) ,阈值可能会降低,所以在这样的平台上使用5000位位集时请记住这一点。然而,我认为,在此之前的某个地方,你应该问自己一个bitset是否真的是容器的正确选择。
答案 1 :(得分:-1)
如果从范围初始化很重要,您可以考虑使用std :: vector
它有来自迭代器对的构造函数