saber que puede pequeña mediana mapas mapa grande geografia escala entre ejemplos diferencia como c++ stl iterator

c++ - que - ¿Qué sucede si se llama a borrar() en un elemento del mapa mientras se itera de principio a fin?



escala pequeña en geografia (3)

En el siguiente código, recorro un mapa y pruebo si un elemento necesita ser borrado. ¿Es seguro borrar el elemento y seguir iterando o necesito recolectar las claves en otro contenedor y hacer un segundo ciclo para llamar al erase ()?

map<string, SerialdMsg::SerialFunction_t>::iterator pm_it; for (pm_it = port_map.begin(); pm_it != port_map.end(); pm_it++) { if (pm_it->second == delete_this_id) { port_map.erase(pm_it->first); } }

ACTUALIZACIÓN: Por supuesto, luego leí esta pregunta que no pensé que estaría relacionada, pero responde mi pregunta.


C ++ 11

Esto se ha corregido en C ++ 11 (o el borrado se ha mejorado / ha sido coherente en todos los tipos de contenedor).
El método de borrado ahora devuelve el siguiente iterador.

auto pm_it = port_map.begin(); while(pm_it != port_map.end()) { if (pm_it->second == delete_this_id) { pm_it = port_map.erase(pm_it); } else { ++pm_it; } }

C ++ 03

Borrar elementos en un mapa no invalida ningún iterador.
(aparte de los iteradores en el elemento que se eliminó)

En realidad, insertar o eliminar no invalida ninguno de los iteradores:

Ver también esta respuesta:
Técnica de Mark Ransom

Pero necesitas actualizar tu código:
En su código, incrementa pm_it después de llamar a borrar. En este punto, es demasiado tarde y ya está invalidado.

map<string, SerialdMsg::SerialFunction_t>::iterator pm_it = port_map.begin(); while(pm_it != port_map.end()) { if (pm_it->second == delete_this_id) { port_map.erase(pm_it++); // Use iterator. // Note the post increment. // Increments the iterator but returns the // original value for use by erase } else { ++pm_it; // Can use pre-increment in this case // To make sure you have the efficient version } }


Así es como lo hago ...

typedef map<string, string> StringsMap; typedef StringsMap::iterator StrinsMapIterator; StringsMap m_TheMap; // Your map, fill it up with data bool IsTheOneToDelete(string str) { return true; // Add your deletion criteria logic here } void SelectiveDelete() { StringsMapIter itBegin = m_TheMap.begin(); StringsMapIter itEnd = m_TheMap.end(); StringsMapIter itTemp; while (itBegin != itEnd) { if (IsTheOneToDelete(itBegin->second)) // Criteria checking here { itTemp = itBegin; // Keep a reference to the iter ++itBegin; // Advance in the map m_TheMap.erase(itTemp); // Erase it !!! } else ++itBegin; // Just move on ... } }


Así es como lo haría, aproximadamente:

bool is_remove( pair<string, SerialdMsg::SerialFunction_t> val ) { return val.second == delete_this_id; } map<string, SerialdMsg::SerialFunction_t>::iterator new_end = remove_if (port_map.begin( ), port_map.end( ), is_remove ); port_map.erase (new_end, port_map.end( ) );

Hay algo extraño sobre

val.second == delete_this_id

pero acabo de copiarlo de tu código de ejemplo.