1

I have a set where each element in the set is of type shared_ptr, I want to remove an element from the set, in eclipse the element was actually removed but when I test this in bash with valgrind I get a lot of invalid size mistakes ...

So this made me think that maybe there is a different way to remove element of type shared_ptr ?

Every element in the peoplePointer is a class of certain person:

typedef std::shared_ptr<person> peoplePointer;

class AA {
    std::set<peoplePointer> setOfPeople;

public:
    // function getName() return name of the person (person is another class) 
    void removeSomeonefromA(const std::string& name) {
        for (std::set<peoplePointer>::iterator it = setOfPeople.begin();it != setOfPeople.end(); it++) {
            if(name == (*it).get()->getName()) {
                setOfPeople.erase((it));
            }
        }
    }
};
Klaas van Gend
  • 1,105
  • 8
  • 22
kasandra
  • 43
  • 7
  • 2
    Erasing elements from a `std::set` invalidates pointers, references and iterators to that element. `it` is invalidated when erase completes. See [`std::set::erase`](http://en.cppreference.com/w/cpp/container/set/erase). – François Andrieux Jan 23 '18 at 18:42
  • 1
    A solution for `std::map` that should work for `std::set` also. https://stackoverflow.com/questions/800955/remove-if-equivalent-for-stdmap. – R Sahu Jan 23 '18 at 18:44
  • i fixed the mistake now it works – kasandra Jan 23 '18 at 18:47
  • 2
    Possible duplicate of [Deleting elements from STL set while iterating](https://stackoverflow.com/questions/2874441/deleting-elements-from-stl-set-while-iterating) – Daniel Langr Jan 23 '18 at 18:51
  • Thumbs up and thanks for using Valgrind! – Klaas van Gend Jan 23 '18 at 18:54

1 Answers1

4

Idea inspired by remove_if equivalent for std::map.

If you are able to use a C++11 or later compiler, you can use:

void removeSomeonefromA(const string& name)
{
   for (set<peoplePointer>::iterator it = setOfPeople.begin(); it != setOfPeople.end();  /* Empty */ )
   {
      if(name == (*it).get()->getName())
      {
         it = setOfPeople.erase(it);
      }
      else
      {
         ++it;
      }
   }
}

If you are required to use a prior compiler version, you can use:

void removeSomeonefromA(const string& name)
{
   for (set<peoplePointer>::iterator it = setOfPeople.begin(); it != setOfPeople.end();  /* Empty */ )
   {
      if(name == (*it).get()->getName())
      {
         setOfPeople.erase(it++);
      }
      else
      {
         ++it;
      }
   }
}
R Sahu
  • 204,454
  • 14
  • 159
  • 270