Łukasz Przeniosło
Łukasz Przeniosło

Reputation: 2949

Going through and inserting data to std vectors

I never had this kind of problems when using QVector, but unfortunately I cannot use qt in this one. What I am trying to do is to go through 2 vectors which contains points X and Y as doubles.

I am trying to insert some x and y points in between the points that are predefined. The problem is that after second loop everything goes bad, iterators start to get weird values and the points are inserted in the 0 index all the time. This iterator thing is really confusing, I can't understand why I can't insert to my vectors simply using intiger indexes. I tried the C++11 way as well, but didn't give me anything.

The m_x vector represents time in seconds and m_y vector represents temperature. m_x is double, but it can only take integer positive values.

int CProcessData::calculateMidPoints()
{
    if((0 == m_x.size()) || (0 == m_y.size()))
        return 1;

    std::vector<double>::iterator itX = m_x.begin();
    std::vector<double>::iterator itY = m_y.begin();
    double midPointY = 0;

    for (uint32_t i = 0; i < (m_x.size() - 1); i++)
    {
        if (i != m_x[i])
        {
            m_x.insert(itX, (double)i);
            midPointY = (m_y[i - 1] * 1 + m_y[i] * (1 / (m_x[i + 1] - m_x[i]))) /
                        (1 + (1 / (m_x[i + 1] - m_x[i])));
            m_y.insert(itY, midPointY);
        }
        else
        {
            itX++;
            itY++;
        }
    }

    return 0;
}

Upvotes: 0

Views: 83

Answers (1)

NathanOliver
NathanOliver

Reputation: 180585

calling insert() is going to invalidate your iterators.

From http://en.cppreference.com/w/cpp/container/vector/insert:

Causes reallocation if the new size() is greater than the old capacity(). If the new size() is greater than capacity(), all iterators and references are invalidated. Otherwise, only the iterators and references before the insertion point remain valid. The past-the-end iterator is also invalidated.

The insert() function returns a iterator to the inserted element. Since this is a valid iterator you can capture it and use it for the next iteration. Here is a little example of how that works:

std::vector<int> data = { 1, 2, 3, 4, 5 };
auto it = data.begin();
std::advance(it, 3);
for (int i = 0; i < 3; i++)
{
    it = data.insert(it, 9);
    ++it;
}

data will contain { 1, 2, 3, 9, 9, 9, 4, 5 } at the end of the for loop.

Upvotes: 1

Related Questions