1

I would like to remove an element from a vector. For example:

// object that is in the vector: MyClass obj;
// vector looks as so: vector<MyClass*> pVector;

pVector.remove(obj);
basickarl
  • 37,187
  • 64
  • 214
  • 335

3 Answers3

5

This will remove the object based purely on the pointer. Ideally, you would have comparison functions for your MyClass objects that actually check the objects to see if they are the same.

pVector.erase(std::remove(pVector.begin(), pVector.end(), obj), pVector.end());
Aesthete
  • 18,622
  • 6
  • 36
  • 45
3

Your question isn't well-defined, but I will provide you with two answers. I am assuming here based on your code that obj is not a pointer, which means that we are comparing an object to pointers to objects. This requires a custom functor.

The first answer is how to remove all elements of the vector where the value of the pointed-to element is equal to obj. This assumes that there is an operator== that can be applied to MyClass objects.

pVector.erase(std::remove_if(pVector.begin(), pVector.end(),
                             [&obj](MyClass * i) { return i && (*i == obj); }));

The second will remove at most one element, if it is found:

auto e = std::find(pVector.begin(), pVector.end(),
                   [&obj](MyClass * i) { return i && (*i == obj); });

if (e != pVector.end()) {
    pVector.erase(e);
}

The lambda syntax requires C++11. If you don't have access to C++11 then you will have to build a functor by hand:

template <typename T>
class pointer_is_equal_to_object
{
public:
    explicit pointer_is_equal_to_object(T const &);

    bool operator()(T const *) const;

private:
    T const & value;
}

template <typename T>
pointer_is_equal_to_object<T>::pointer_is_equal_to_object(T const & v) : value(v) {}

template <typename T>
bool pointer_is_equal_to_object<T>::operator()(T const * p) const
{
    return p && (*p == value);
}

Then, for example, you could use:

pVector.erase(std::remove_if(pVector.begin(), pVector.end(),
                             pointer_is_equal_to_object<MyClass>(obj)));

Note that this complexity goes away if you stop using pointers and just use std::vector<MyClass>. Then your operator== can be applied directly and you can just do:

pVector.erase(std::remove(pVector.begin(), pVector.end(), obj));
cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • the std::find can not accept an UnaryPredicate as third paramter but std::find_if can, the above std::find should change to std::find_if in the second answer. – BruceSun Apr 23 '22 at 08:43
1

Assuming C++11, and that you want to remove ANY elements matching obj, and not the exact obj... but you should be able to figure it out from here either way :)

http://en.wikipedia.org/wiki/Erase-remove_idiom

And for fun, here's an example: http://ideone.com/6ILYvo

#include <algorithm>
#include <vector>

std::vector<MyClass*> v;
MyClass * toberemoved = new MyClass();

//v gets populated...

auto itr = std::remove_if(v.begin(),v.end(), [&](MyClass* a){return *a == *toberemoved;});

v.erase(itr,v.end());
druckermanly
  • 2,694
  • 15
  • 27