Adding an element to a Vector while iterating over it

15,813

Solution 1

The act of adding or removing an item from a std::vector invalidates existing iterators. So you cannot use any kind of loop that relies on iterators, such as for each, in, range-based for, std::for_each(), etc. You will have to loop using indexes instead, eg:

int main()
{
    std::vector<MyClass> myVector;
    myVector.push_back('1');
    myVector.push_back('2');
    myVector.push_back('3');
    std::vector<MyClass>::size_type size = myVector.size();
    for (std::vector<MyClass>::size_type i = 0; i < size; ++i)
    {
        if (myVector[i].name == '2')
        {
             myVector.push_back('4');
             ++size; // <-- remove this if you want to stop when you reach the new items
        }
    }
    return 0;
}

Solution 2

As pointed out by pyon, inserting elements into a vector while iterating over it (via iterators) doesnt work, because iterators get invalidated by inserting elements. However, it seems like you only want to push elements at the back of the vector. This can be done without using iterators but you should be careful with the stop condition:

std::vector<MyClass> myVector;
size_t old_size = myVector.size();
for  (int i=0;i<old_size;i++) {
    if (myVector[i].name == '2') { myVector.push_back(MyClass('4')); }
}
Share:
15,813
Alex
Author by

Alex

Updated on June 05, 2022

Comments

  • Alex
    Alex 12 months

    As the title says, I want to add an element to a std::vector in certain cases while iterating through the vector. With the following code, I'm getting an error "Debug assertion failed". Is it possible to achieve what I want to do?

    This is the code I have tested:

    #include <vector>
    class MyClass
    {
    public:
        MyClass(char t_name)
        {
            name = t_name;
        }
        ~MyClass()
        {
        }
        char name;
    };
    int main()
    {
        std::vector<MyClass> myVector;
        myVector.push_back(MyClass('1'));
        myVector.push_back(MyClass('2'));
        myVector.push_back(MyClass('3'));
        for each (MyClass t_class in myVector)
        {
            if (t_class.name == '2')
                 myVector.push_back(MyClass('4'));
        }
        return 0;
    }
    

    EDIT:

    Well, I thought for each was standard C++, but it seems that it's a Visual Studio feature:

    for each, in

    Visual c++ "for each" portability

  • bb1950328
    bb1950328 almost 2 years
    why have a variable for the size? i < myVector.size() works too
  • Remy Lebeau
    Remy Lebeau almost 2 years
    @bb1950328 Doing so forces a function call to size() on every iteration, whereas when using a variable, there is only 1 function call to size() before the loop is entered. If size() is inlined, it likely doesn't really matter either way, but if size() is not inlined then performance may be affected if the vector size is large. More importantly, your approach doesn't allow the loop to stop when the end of the old items is reached, knowing that none of the new items will match the condition being tested for.
  • bb1950328
    bb1950328 almost 2 years
    makes sense, thanks for the clarification