سؤال

I have an iterator for a vector that I want to delete certain elements in the vector. Running the code, no errors come up in the compiling, but after executing I receive a message saying 'Debug assertion failed!'. Could somebody tell me what's wrong with my iterator?

int function(unsigned int n, unsigned int m)
{
vector<int> vec1;

    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);

vector<int>::iterator vec2;

for (vec2 = vec1.begin(); vec2 != vec1.end(); ++vec2)
{
    if(*vec2 == 4)
    {
    vec1.erase(vec2);
    }
}

return 0;
}
هل كانت مفيدة؟

المحلول

The erase method will invalid your iterator. You must write:

for (vec2 = vec1.begin(); vec2 != vec1.end(); )
{
    if(*vec2 == 4)
      vec2 = vec1.erase(vec2);
    else
      ++vec2;
}

Note that you must increment vec2 only if the element is not erased. If you increment vec2 at each iteration, you will miss some elements, because erase returns an iterator that pointed on the element next to the erased one.

نصائح أخرى

The problem is that you are deleting from the vector being iterated. Once you have deleted an object from the vector, all its iterators are invalidated; subsequent access to them is undefined behavior.

To fix this problem, you can use indexing, and start walking the vector from the end. This way you would be able to decrement the index on each iteration, regardless of whether you deleted an object or not.

Vector elements are stored in contiguous memory, so when you erase an element of a vector the tail elements (the ones after the erased elements) have to be "shifted", thus all iterators into that part of the vector are invalidated.

The usual way to delete all elements that are equal to some value is using standard algorithm std::remove along with member function erase For example

void function()
{
   vector<int> vec1;

    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);

   vec1.erase( std::remove( vec1.begin(), vec1.end(), 4 ), vec1.end() );
}

if you want to delete only one element that is equal to 4 you could write

void function()
{
   vector<int> vec1;

    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);

    auto it = std::find( vec1.begin(), vec1.end(), 4 );

    if ( it != vec1.end() ) vec1.erase( it );
}

If you want to delete all elements that are equal to 4 using a loop you should write

void function()
{
    vector<int> vec1;

    vec1.push_back(3);
    vec1.push_back(4);
    vec1.push_back(5);

    for ( auto it = vec1.begin(); it != vec1.end(); )
    {
        if ( *it == 4 ) it = vec1.erase( it );
        else ++it;
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top