Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ Keeping track of start iterator while adding items

I am trying to do a double loop across a std::vector to explore all combinations of items in the vector. If the result is good, I add it to the vector for another pass. This is being used for an association rule problem but I made a smaller demonstration for this question. It seems as though when I push_back it will sometimes change the vector such that the original iterator no longer works. For example:

    std::vector<int> nums{1,2,3,4,5};
    auto nextStart = nums.begin();
    while (nextStart != nums.end()){
        auto currentStart = nextStart;
        auto currentEnd = nums.end();
        nextStart = currentEnd;
        for (auto a = currentStart; a!= currentEnd-1; a++){
            for (auto b = currentStart+1; b != currentEnd; b++){
                auto sum = (*a) + (*b);
                if (sum < 10) nums.push_back(sum);
            }
        }
    }

On some iterations, currentStart points to a location that is outside the array and provides garbage data. What is causing this and what is the best way to avoid this situation? I know that modifying something you iterate over is an invitation for trouble…

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

nums.push_back(sum);

push_back invalidates all existing iterators to the vector if push_back ends up reallocating the vector.

That’s just how the vector works. Initially some additional space gets reserved for the vector’s growth. Vector’s internal buffer that holds its contents has some extra room to spare, but when it is full the next call to push_back allocates a bigger buffer to the vector’s contents, moves the contents of the existing buffer, then deletes the existing buffer.

The shown code creates and uses iterators for the vector, but any call to push_back will invalidate the whole lot, and the next invalidated vector dereference results in undefined behavior.

You have two basic options:

  1. Replace the vector with some other container that does not invalidate its existing iterators, when additional values get added to the iterator

  2. Reimplement the entire logic using vector indexes instead of iterators.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading