c++ - 使用 for 循环删除 vector 中的元素

标签 c++ for-loop vector segmentation-fault erase

如何使用 for 循环按索引从 vector 中删除元素?我收到 vector 超出范围错误。我在下面有一个示例代码。

 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]);
 }

我认为这是因为我的 vector 的大小在每次迭代中都减小了,因此它无法访问索引 2。

最佳答案

您通常会使用 erase–remove idiom有效地从 vector 中删除多个元素(一个一个地删除它们通常效率较低,而且正如您所见,并不总是微不足道的)。在其最一般的形式中,成语看起来像这样:

data.erase(remove_algorithm(begin(data), end(data)), end(data));

在您的情况下,remove_algorithm 基于另一个 vector 中的索引,因此我们也需要提供这些索引:

data.erase(
    remove_indices(begin(data), end(data), begin(to_erase), end(to_erase)),
    end(data));

不幸的是,这样的算法不包含在标准库中。然而,自己编写 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;
}

在这里,我们首先对要删除的索引从大到小进行排序。接下来,我们遍历这些索引。然后我们(最有效地)将当前位置(要删除)和 vector 末尾之间的所有元素向前移动一个。随后,末尾减一(以说明元素被删除的事实)。

Live code


1 *咳咳* 一旦你删除了代码中所有愚蠢的拼写错误。

关于c++ - 使用 for 循环删除 vector 中的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35650564/

相关文章:

scala - 隐含的太多了!

c++ - map 什么时候变得比两个 vector 更好?

C++图像处理,粒子计数

c++ - 追加 __FUNCTION__ 宏提供的字符串

c++ - 左值到右值的转换

c# - 多线程时循环索引超出范围 ArgumentOutOfRangeException

javascript - 开始使用 javascript,有一个问题

r - 如果满足条件,则循环将列粘贴在一起

c++ - 在 C++ 中从成对 vector 转换为两个独立 vector 的最快方法

C++ - 将数组传递给方法