Erasing item in a for(-each) auto loop

怎甘沉沦 提交于 2019-12-18 04:18:12

问题


Is there a way to erase specific elements when using a auto variable in a for loop like this?

for(auto a: m_Connections)
{
    if(something)
    {
        //Erase this element

    }
}

I know I can either do say

for(auto it=m_map.begin() ...

or

for(map<int,int>::iterator it=m_map.begin() ...

and manually increment the iterator (and erase) but if I could do it with less lines of code I'd be happier.

Thanks!


回答1:


No, there isn't. Range based for loop is used to access each element of a container once.

Every time an element is removed from the container, iterators at or after the erased element are no longer valid (and given the implementation of the range-based-for this is a problem).

You should use the normal for loop (or a while) if you need to modify the container as you go along.

If you want to erase elements for which a predicate returns true, a good way is:

m_Connections.erase(
  std::remove_if(m_Connections.begin(),
                 m_Connections.end(),
                 [](Type elem) { return predicate(elem); }),
  m_Connections.end());

std::remove_if doesn't mix iteration logic with the predicate.




回答2:


You can't. A range-based loop makes a simple iteration over a range simpler, but doesn't support anything that invalidates either the range, or the iterator it uses. Of course, even if that were supported, you couldn't efficiently erase an element without access to the iterator.

You'll need an old-school loop, along the lines of

for (auto it = container.begin(); it != container.end();) {
    if (something) {
        it = container.erase(it);
    } else {
        ++it;
    }
}

or a combination of container.erase() and std::remove_if, if you like that sort of thing.




回答3:


You need the iterator if you want to erase an element from a container.
And you can't get the iterator from the element itself -- and even if you could, for instance with vector, the iterator that range-based for internally uses would be invalidated in the next step causing undefined behavior.

So the answer is: No, in its classic usage you can't. range-based for was solely designed for convenient iteration of all elements in a range.




回答4:


push all elements into array and then do pop operation to remove the item



来源:https://stackoverflow.com/questions/26524794/erasing-item-in-a-for-each-auto-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!