【发布时间】:2020-01-18 22:17:37
【问题描述】:
我在 C++ 中有一个自定义的 bitset 类实现。我经常迭代在 bitset 中设置的位的索引(即对于 bitset '10011',我想迭代数字 0、3、4。)这种迭代可以实现如下:
struct Bitset {
uint64_t* data_;
size_t chunks_;
std::vector<int> Elements() const {
std::vector<int> ret;
for (size_t i=0;i<chunks_;i++){
uint64_t td = data_[i];
while (td) {
ret.push_back(i*BITS + __builtin_ctzll(td));
td &= ~-td;
}
}
return ret;
}
};
void Iterate(Bitset bitset) {
for (int b : bitset.Elements()) {
std::cout << "bit: " << b << std::endl;
}
}
上面的实现为迭代提供了干净的代码,但它涉及到向量的不必要的堆分配。以下基本上内联 Elements() 函数的版本通常更快:
void Iterate(Bitset bitset) {
int chunks = bitset.chunks_;
for (int i = 0; i < chunks; i++) {
uint64_t td = bitset.data_[i];
while (td) {
std::cout << "bit: " << i*BITS + __builtin_ctzll(td) << std::endl;
td &= ~-td;
}
}
}
什么是实现迭代抽象的好方法,这样它就和上面的版本一样干净,而且没有性能成本。
【问题讨论】:
-
您不妨看看
std::vector<bool>是如何解决这个确切问题的。 -
返回一个int的向量很占内存,为什么不写一个迭代器呢?哦,这是你的问题。一个好方法是编写一个
begin和end方法并编写一个迭代器。i*BITS- 什么是“BITS”?为什么i*BITS + __builtin_ctzll(td)会这样做?它的代码比普通的value && ( << position)更好吗?我无法理解i*BITS能做什么 -i只会增加并且与data_[i]值无关,所以我认为这是一个错误。 -
一个 C++20 协程?将函数作为参数的 Bitset::for_each?
标签: c++ performance abstraction