Search code examples
c++vectoriteratorerase

C++ Vector Iterator: Compare and Erase Two Elements


I have a std::vector<Shape*> called scene which stores pointers to Shapes. I need to be able to iterate through the vector, comparing the shape pointed to by the iterator with the next shape in the iterator. If the return of s1->intersects(*s2) is true, I need to remove both s1 and s2 from the vector. The following code isn't correct, I get an exception vector interator is not incrementable.

How can I solve this problem?

while (scene.size() > 1)
{
    for (std::vector<Shape*>::iterator it = scene.begin(); it != scene.end() - 1; it++)
    {
        Shape* s1 = (*it);
        Shape* s2 = (*(it + 1));

        if (s1->intersects(*s2))
        {
            delete s1;
            delete s2;

            // Remove the pointers to s1 and s2 from the vector.
            it = scene.erase(it);
            it = scene.erase(it);
        }
    }
}

Solution

  • Seeing as how your code already assumes there are no null pointers in the vector, you can use a null pointer as a marker for deletion, simplifying the logic greatly by separating the marking from the erasing.

    for (std::vector<Shape*>::iterator it = scene.begin(); it < scene.end() - 1; ++it)
    {
        Shape*& s1 = (*it);
        Shape*& s2 = (*(it + 1));
        if (s1->intersects(*s2))
        {
            delete s1;
            delete s2;
            s1 = NULL;
            s2 = NULL;
            ++it;
        }
    }
    
    scene.erase(std::remove(scene.begin(), scene.end(), NULL), scene.end());
    

    As an aside, your original code could have probably been fixed by changing it != scene.end() - 1 to it < scene.end() - 1. Because if you end up erasing the last two elements, you'll have an iterator which is equal to scene.end(), which satisfies the condition it != scene.end() - 1, and the loop will try to increment it.