Erasing an element in a for (-each) automatic loop

Is there a way to remove certain elements when using an automatic variable in a for loop as follows?

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

I know that I can either say

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

or

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

and manually increase the iterator (and erase), but if I could do this with fewer lines of code, I would be happier.

Thanks!

+5
source share
4 answers

No no. A loop-based range is used to access each element of the container once.

Each time an element is removed from the container, iterators in or after the element to be erased are no longer valid (and range implementation is given β€” this is a problem).

You should use a regular loop (or while ) while if you need to change the container as you go.

If you want to remove elements for which the predicate returns true , a good way:

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

std :: remove_if does not mix iteration logic with predicate.

+5
source

You can not. A range-based loop simplifies simple iteration in a range, but does not support anything that is invalid for either the range or the iterator that it uses. Of course, even if this was supported, you would not be able to effectively erase an element without access to the iterator.

You will need an old-school cycle line by line

 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 such a thing.

+5
source

You need an iterator if you want to remove an item from the container.
And you cannot get an iterator from the element itself - and even if you could, for example, with vector , a range-based iterator for internal applications would be invalid in the next step, causing undefined behavior. <w>

So, the answer: No, in its classic use you cannot. based on the range, was intended solely for convenient iteration of all elements in the range.

+3
source

push all the elements into an array and then perform the pop operation to remove the element

+1
source

Source: https://habr.com/ru/post/1205347/


All Articles