Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::erase and std::remove combination to delete specific element doesn't work for specific example

Tags:

#include <vector>
#include <algorithm>

using namespace std;

int main() {
    vector<int> a = {1,2,3,7,1,5,4};
    vector<int> b = {6,7,4,3,3,1,7};
    a.erase(remove(a.begin(),a.end(),a[0]),a.end());
    b.erase(remove(b.begin(),b.end(),b[0]),b.end());

    return 1;
}

For this specific example, my GNU gdb Ubuntu 7.7.1 states that at return 1 line: a = {2,3,7,1,5,4} which is not expected (only deletes one 1), and b = {7,4,3,3,1} which is not expected.

My expectation is b should be a=2,3,7,5,4 and b=7,4,3,3,1,7.

What's happening here?

like image 488
user3064869 Avatar asked Feb 25 '15 14:02

user3064869


People also ask

How do you remove a specific element from a vector in C++?

The C++ vector has many member functions. Two of these member functions are erase() and pop_back(). pop_back() removes the last element from the vector. In order to remove all the elements from the vector, using pop_back(), the pop_back() function has to be repeated the number of times there are elements.

How do I remove an item from a vector file?

All the elements of the vector are removed using clear() function. erase() function, on the other hand, is used to remove specific elements from the container or a range of elements from the container, thus reducing its size by the number of elements removed.


1 Answers

The declaration of std::remove() looks like

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);

Note that the last parameter is a reference. Thus after compilation it effectively pass the address of the specified element.

By remove(a.begin(), a.end(), a[0]), something indicating the address to the 0th element of a is passed in. When remove() is running, once the 0th element is handled, the value pointed by the reference passed in changed, which leads to the unexpected result.

To get expected result, make a copy before calling std::remove().

int toberemoved = a[0];
a.erase(remove(a.begin(),a.end(),toberemoved),a.end());
like image 161
timrau Avatar answered Sep 25 '22 12:09

timrau