Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
133 views
in Technique[技术] by (71.8m points)

c++ - Algorithm for removing elements

I understand there is erase-remove idiom for c++. And the remove method under <algorithm> will move target elements to the back of the range.

However, the output below is confusing to me.

#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;
}

The output is:

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

There are two questions here:

  1. For "After removing 20", why are there 10 mixed with 20 at the back? 10 30 30 10 10 20 10 10 20

  2. For "use pend:", why does it fail to print the last two more 10's? There are five 10's in the original vector, and 10's are not supposed to be removed?

From the library, remove() method returns the iterator pend

template ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val); An iterator to the element that follows the last element not removed. The range between first and this iterator includes all the elements in the sequence that do not compare equal to val.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

From the array:

10 20 30 20 30 20 10 10 20

When you remove all 20, you expect to get:

10 30 30 10 10

But std::remove just shifts the items, it lets the remaining values unspecified:

Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values

So you get:

10 30 30 10 10 xx xx xx xx
               ^
               pend

Which explains your results.

If you need to erase the items, call vec.erase(pend, vec.end()):

A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...