Search code examples
qtiteratorqt4qmapqhash

Qt Delete Items from QMultiHash while Iterating


I want to delete items out of my QMultiHash. Looking at the docs, I believe I am doing it correctly but it always crashes after the first delete. What am I doing wrong?

Here is my code:

for (QMultiHash<int, Frame*>::iterator i = m_FrameBuffer.begin(); i != m_FrameBuffer.end(); ++i) {
    if ( (frameNumber - i.key()) >= ( 5 ) ) { // Delete frames 5 frames old or more
        qDebug() << "DELETE ==> Key:" << i.key() << "Value:" << i.value() << " Difference: " << (frameNumber - i.key());
        int removed = m_FrameBuffer.remove(i.key());
        qDebug() << "Removed this many: " << removed;
    }
}

Here is the output:

FRAME COUNT:  1 
FRAME COUNT:  2 
FRAME COUNT:  3 
FRAME COUNT:  4 
FRAME COUNT:  5 
DELETE ==> Key: 2 Value: Frame(0x138a400)  Difference:  5 
Removed this many:  1 
The program has unexpectedly finished.

Solution

  • Your iterator becomes invalid after you remove items from a container while iterating it. Try this:

    QList<int> keys = m_FrameBuffer.keys();
    foreach (int key, keys)
    {
        int diff = frameNumber - key;
        if (diff >= 5)
        {
            qDebug() << "DELETE ==> Key:" << key 
                     << "Value:" << m_FrameBuffer.value(key) 
                     << "Difference: " << diff;
            int removed = m_FrameBuffer.remove(key);
            qDebug() << "Removed this many: " << removed;
        }
    }
    

    Also you can use QMutableHashIterator for it:

    QMutableHashIterator<int, Frame*> it(m_FrameBuffer);
    while (it.hasNext())
    {
        it.next();
        int key = it.key();
        int diff = frameNumber - it.key();
        if (diff >= 5)
        {
            qDebug() << "Items to be removed:" 
                     << m_FrameBuffer.values(it.key()).size();
            it.remove();
        }
    }