Home > OS >  C Keeping track of start iterator while adding items
C Keeping track of start iterator while adding items

Time:11-25

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...

CodePudding user response:

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.

  • Related