0

Aim : Create a vector. Use remove_if on it

#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
#include<functional>
using namespace std;
int main()
{
    int negative_count=0;
    vector<int> v = { 2, -1, -3, 5, -5, 0, 7 };
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    vector<int>::iterator new_it=remove_if(v.begin(), v.end(), bind2nd(greater<int>(), -1));
    v.erase(new_it);
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
    cout << endl;


}

The output:Output

The remove_if condition is to remove numbers greater than -1. Why is it displaying -5 twice?The output after remove_if should be -1 -3 -5 5 0 7 according to me. Also if i use

V.erase(new_int,v.end())

The output is fine: -1 -3 -5

Omkar
  • 791
  • 1
  • 9
  • 26

4 Answers4

5

When you call std::remove/remove_if, it moves elements which don't satisfy the condition to the front of the range. The values of any remaining elements (starting from the position of the returned iterator) are unspecified. Some people seem to think that it swaps the elements such that the ones which satisfy the condition are moved to the back. But the algorithm is not specified to do this. If that's the result you want, then the algorithm you are looking for is std::partition.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
2

The information said replace_if returns a pointer to a new range,So i expected the new range after my output

  1. remove_if returns an iterator.

Namely a one past the end iterator of the range containing only elements that do NOT satisfy the condition. There is no guarantee that the rest of the range will contain all other elements.

std::vector<int> v{ 2, -1, -3, 5, -5, 0, 7 };
auto new_end = std::remove_if(v.begin(), v.end(), [](auto i){ return i > -1; });

// now the range [v.begin(), new_end) contains only elements that are not > -1
// contents of [new_end, v.end()) are unspecified

for(auto i = v.begin(); i!=new_end; ++i)
{
    std::cout << *i;
}
  1. erase-remove idiom requires you to specify the whole range of elements to be removed.

Thats because you'd require every item that does match the condition to be removed. not only one.

v.erase(new_end, v.end());
Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
1

Erase elements Removes from the vector either a single element (position) or a range of elements ([first,last)).

Above reference is from http://www.cplusplus.com/reference/vector/vector/erase/ This means that in your case, you only erase one element from the vector which is pointed by the iterator returned by remove_if() function. You need to define a ranged as you mentioned at the end:

V.erase(new_int,v.end())
Khai Nguyen
  • 103
  • 1
  • 7
0

Because remove_if doesn't actually remove anything, it only copies/moves elements satisfying predicate to the end. So you have to write v.erase(new_it, v.end()). Link

K117
  • 118
  • 1
  • 7