删除元素的算法

时间:2017-01-27 10:06:30

标签: c++ algorithm

我知道c ++有擦除删除习惯用法。 remove下的<algorithm>方法会将目标元素移动到范围的后面。

但是,下面的输出对我来说很困惑。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<int> vec = {10, 20, 30, 20, 30, 20, 10, 10, 20};

    auto pend = remove(vec.begin(), vec.end(), 20);
    cout << "After removing 20: " << endl;
    for (const auto& x : vec) {
        cout << x << " ";
    }
    cout << endl;

    cout << "use pend: " << endl;
    for (auto p = vec.begin(); p != pend; p++) {
        cout << " " << *p;
    }

    cout << endl;
    return 0;
}

输出结果为:

After removing 20:
10 30 30 10 10 20 10 10 20
use pend:
10 30 30 10 10

这里有两个问题:

  1. 对于&#34;在删除20&#34;之后,为什么有10个与20混合在后面? 10 30 30 10 10 20 10 10 20

  2. 对于&#34;使用pend:&#34;,为什么它无法打印最后两个10&?s?原始载体中有5个10,不应该删除10个?

  3. 从库中,remove()方法返回迭代器pend

    模板   ForwardIterator删除(ForwardIterator first,ForwardIterator last,const T&amp; val); 未删除的最后一个元素后面的元素的迭代器。 first和this迭代器之间的范围包括序列中不比较等于val的所有元素。

2 个答案:

答案 0 :(得分:13)

来自阵列:

10 20 30 20 30 20 10 10 20

当您删除所有20时,您希望获得:

10 30 30 10 10

但是std::remove只是移动了项目,它会让剩下的值unspecified

  

指向新逻辑端和范围物理端之间的元素的迭代器仍然是可解除引用的,但元素本身具有未指定的值

所以你得到:

10 30 30 10 10 xx xx xx xx
               ^
               pend

这解释了你的结果。

如果您需要删除项目,请拨打vec.erase(pend, vec.end())

  

调用remove之后通常会调用容器的erase方法,该方法会擦除未指定的值并减小容器的物理大小以匹配其新的逻辑大小。

答案 1 :(得分:2)

在C ++中,这被称为erase-remove idiom。来自维基百科页面:

  

擦除 - 删除习语是一种常见的C ++技术,用于从C ++标准库容器中删除满足特定条件的元素。

另见Scott Meyers Effective C ++书籍。