Rui*_*iQi 4 c++ for-loop vector erase segmentation-fault
如何使用for循环通过索引从矢量中擦除元素?我得到一个超出范围错误的向量.我在下面有一个示例代码.
vector<int> to_erase = {0, 1, 2};
vector<int> data = {3, 3, 3, 3};
for(int i = 0; i < to_erase.size(); i++) {
data.erase(data.begin() + to_erase[i]);
}
Run Code Online (Sandbox Code Playgroud)
我认为这是因为我的向量的大小在每次迭代时都会减少,因此它无法访问索引2.
您通常会使用擦除删除习惯用法有效地从向量中删除多个元素(逐个删除它们通常效率较低,而且,正如您所见,并非总是微不足道).在最一般的形式中,成语看起来像这样:
data.erase(remove_algorithm(begin(data), end(data)), end(data));
Run Code Online (Sandbox Code Playgroud)
在你的情况下,它remove_algorithm
是基于另一个向量中的索引,所以我们也需要提供这些:
data.erase(
remove_indices(begin(data), end(data), begin(to_erase), end(to_erase)),
end(data));
Run Code Online (Sandbox Code Playgroud)
不幸的是,这种算法不包含在标准库中.然而,写自己1是微不足道的:
template <typename It, typename It2>
auto remove_indices(It begin, It end, It2 idx_b, It2 idx_e) -> It {
using idx_t = typename std::iterator_traits<It2>::value_type;
std::sort(idx_b, idx_e, std::greater<idx_t>{});
for (; idx_b != idx_e; ++idx_b) {
auto pos = begin + *idx_b;
std::move(std::next(pos), end--, pos);
}
return end;
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们首先对要从最大到最小的索引进行排序.接下来,我们循环这些索引.然后,我们(最有效地)将当前位置(待删除)和向量末尾之间的所有元素向前移动一.随后,结束减少一个(考虑到元素被删除的事实).
1*Ahem*一旦你删除了代码中的所有愚蠢的拼写错误.
归档时间: |
|
查看次数: |
1324 次 |
最近记录: |