Can you remove elements from a std::list while iterating through it?

后端 未结 13 1045
长情又很酷
长情又很酷 2020-11-22 06:30

I\'ve got code that looks like this:

for (std::list::iterator i=items.begin();i!=items.end();i++)
{
    bool isActive = (*i)->update();
    /         


        
13条回答
  •  日久生厌
    2020-11-22 06:53

    You need to do the combination of Kristo's answer and MSN's:

    // Note: Using the pre-increment operator is preferred for iterators because
    //       there can be a performance gain.
    //
    // Note: As long as you are iterating from beginning to end, without inserting
    //       along the way you can safely save end once; otherwise get it at the
    //       top of each loop.
    
    std::list< item * >::iterator iter = items.begin();
    std::list< item * >::iterator end  = items.end();
    
    while (iter != end)
    {
        item * pItem = *iter;
    
        if (pItem->update() == true)
        {
            other_code_involving(pItem);
            ++iter;
        }
        else
        {
            // BTW, who is deleting pItem, a.k.a. (*iter)?
            iter = items.erase(iter);
        }
    }
    

    Of course, the most efficient and SuperCool® STL savy thing would be something like this:

    // This implementation of update executes other_code_involving(Item *) if
    // this instance needs updating.
    //
    // This method returns true if this still needs future updates.
    //
    bool Item::update(void)
    {
        if (m_needsUpdates == true)
        {
            m_needsUpdates = other_code_involving(this);
        }
    
        return (m_needsUpdates);
    }
    
    // This call does everything the previous loop did!!! (Including the fact
    // that it isn't deleting the items that are erased!)
    items.remove_if(std::not1(std::mem_fun(&Item::update)));
    

提交回复
热议问题