2

A two-dimension vector: (I want to go through vector and if I find the same name as "and", then delete or erase it, but why it can only work with it1 not it2? how to fix it?)

vector<Animals>numberOfAnimals(12);
vector<vector<Animals>>all(4,numberOfAnimals);

void delete_item(vector<vector<Animals>>&all,string ans)
{
    for (auto it1=all.begin();it1!=all.end();it1++)
    {
        for (auto it2=(*it1).begin();it2!=(*it1).end();it2++)
        {
            if ((*it2).getter_name()==ans)
            {
                all.erase(it1);  //no error
                all.erase(it2--); //error
            }
        }
    }
}
Richard
  • 31
  • 3
  • The operator `->` can be used instead of `(*it).`. For example `it1->end()` instead of `(*it1).end()`. – François Andrieux Oct 29 '19 at 17:21
  • `it1` is the iterator of `all` which is type `vector>` where-as `it2` is the iterator to a `vector`; you want to do `it1->erase(it2)` – ChrisMM Oct 29 '19 at 17:24
  • Related [Deleting elements from std::set while iterating](https://stackoverflow.com/questions/2874441/deleting-elements-from-stl-set-while-iterating). – François Andrieux Oct 29 '19 at 17:32
  • `vector` is probably not what you think it is. Each element in that vector holds _one_ `Animals`. What does the definition of `Animals` look like? – Ted Lyngmo Oct 29 '19 at 17:42

1 Answers1

1

all is a vector of vectors. it1 is an iterator to all, so it can be passed to all.erase. it1 refers to one of the vectors inside all.

it2 is not an iterator to all, so it cannot be passed to all.erase. it2 is an iterator to the vector *it1 which is a vector of Animals. it2 can be passed to it1->erase. it2 refers to one of the Animals in *it1.


However, note that erasing an iterator to vector invalidates it. it1 and it2 are still used in the loop in a way that is not allowed to be done on an invalid iterator. Thus using erase in the loop without fixing the iterator has undefined behaviour.

The idiomatic way to selectively erase some elements of a container is erase-remove:

auto predicate = [&ans](const Animals& a) {
    return a.getter_name()==ans;
};
for(std::vector<Animals>& v : all) {
    v.erase(std::remove_if(v.begin(), v.end(), predicate));
}

This removes all of the Animals that match the predicate in each of the vectors within all.

eerorika
  • 232,697
  • 12
  • 197
  • 326