我将把这个答案反过来写。多多包涵,希望你能理解。
让我们首先编写一个包装器,让我们只迭代选定的项目:
#include <iostream>
#include <vector>
struct SomeStruct {};
struct selected_item {
std::vector<SomeStruct>& items;
std::vector<size_t>& selection;
struct iterator {
std::vector<SomeStruct>& items;
std::vector<size_t>::iterator selection_iterator;
SomeStruct& operator *(){
return items[*selection_iterator];
}
iterator& operator++(){
++selection_iterator;
return *this;
}
bool operator!=(const iterator& other){
return selection_iterator != other.selection_iterator;
}
};
iterator begin() { return {items,selection.begin()}; }
iterator end() { return {items,selection.end()};}
};
int main() {
std::vector<SomeStruct> items{{},{},{},{}};
std::vector<size_t> selection{1,3};
for (auto& i : selected_item{items,selection}){
std::cout << "item selected\n";
}
}
使用它,您现在可以编写一个循环,将所选项目从 items 移动到新向量中,然后将该新向量移动到项目中:
int main() {
std::vector<SomeStruct> items{{},{},{},{}};
std::vector<size_t> selection{1,3};
std::vector<SomeStruct> temp_items;
temp_items.reserve(selection.size());
for (auto& i : selected_item{items,selection}){
temp_items.emplace_back(std::move(i));
}
items = std::move(temp_items);
}
假设SomeStruct可以移动,这不会复制任何SomeStruct。然而,搬家也不是免费的。根据您实际要从items 中删除元素的原因(为什么不首先填充所选项目的向量,而不是填充索引向量?)您还可以考虑完全跳过移动并仅使用上述内容包装器对所选项目执行任何您想做的事情。由于选择了 90% 的项目,可能是内存的节省和更有效的元素访问(由于较小的向量)并没有超过移动,所以您不妨直接这样做:
int main() {
std::vector<SomeStruct> items{{},{},{},{}};
std::vector<size_t> selection{1,3};
for (auto& i : selected_item{items,selection}){
do_something_with_selected_item(i);
}
}
另一种选择是实际从items 中删除元素。我没有考虑它,因为我预计它会相当昂贵。我可能错了。与往常一样,要知道您需要衡量什么更有效。
PS: 包装器是用 gcc 测试的。我发现编写自定义迭代器有点烦人,不确定它是否需要 operator== 或后增量。我只实现了让 gcc 满意的必要条件。