La mejor manera de eliminar in situ un elemento

votos
2

Tengo un conjunto de objetos que iterar, sin embargo, puedo decidir durante la iteración que uno (o más) de esos objetos ahora necesitan ser eliminados.

Mi código es el siguiente:

if( ! m_Container.empty() )
    {
        for(  typedefedcontainer::iterator it = m_Container.begin();
              it != m_Container.end(); 
              ++it  )
        {
            if( ! ( SomeFunction( (*it), test, TEST!, false ))  )
            {
            // If function returns false, delete object.
                m_Container.erase( it );
                AsyncResponseStore::iterator it = m_asyncResponses.begin();
            }

        }


    }

Pero, por supuesto, cuando borro un objeto me sale un error: Map / set iterator no incrementable. ¿Alguien puede sugerir una mejor manera de hacer esto?

Consulte: ¿Qué sucede si llama a erase () en un elemento de mapa mientras itera de principio a fin?

Publicado el 09/12/2008 a las 17:09
fuente por usuario
En otros idiomas...                            


3 respuestas

votos
6

Si el contenedor lo admite (sospecho que el suyo no, pero el título de la pregunta es genérico, puede ser útil para otros si no es así):

struct SomePredicate {
    bool operator()(typedefedcontainer::value_type thing) {
        return ! SomeFunction(thing, "test", "TEST", false);
    }
};

typedefedcontainer::iterator it;
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate());
m_Container.erase(it, m_Container.end());

m_Container debe tener un método de rango de borrado, que incluye cualquier Secuencia o Contenedor Asociativo. Sin embargo, tiene que tener un iterador mutable, y me di cuenta de que originalmente leí mal el mensaje de error: dice "map / set iterator no incrementable". Así que supongo que su contenedor es un mapa o un conjunto.

Tenga en cuenta que los últimos tres podrían ser un trazador de líneas verdaderamente maravilloso, pero este margen es demasiado estrecho para contenerlo.

Además, SomePredicate podría tener un constructor con parámetros para almacenar los parámetros adicionales en SomeFunction, ya que en la vida real supongo que no son constantes.

En realidad, podría deshacerse de SomePredicate por completo si usa boost: bind para construir el functor. Tu única línea sería realmente masiva.

[Editar: Rob Walker señala correctamente en su respuesta una suposición que hago aquí y que la pregunta no establece, que es que todo el borrado se puede aplazar hasta que se complete la iteración y la prueba. Si SomeFunction accede a m_Container por una ruta oculta (por ejemplo, una global, o porque SomeFunction es en realidad una función miembro de esto), y sus resultados dependen del contenido del contenedor, entonces mi código puede no ser equivalente al código del interrogador. Pero creo que mi código es el "a menos que haya una razón para no hacerlo".

Respondida el 09/12/2008 a las 17:39
fuente por usuario

votos
6

Depende del contenedor El contenedor de lista admite la eliminación durante la enumeración al devolver un nuevo iterador del método de borrado que representa el siguiente elemento de la lista. el mapa no es compatible con esto.

Un método simple para el mapa es acumular los elementos que desea borrar en una lista separada, y luego iterar sobre esa lista cuando haya terminado de procesar el mapa para borrar los elementos del mapa. Esto supone que puede aplazar la eliminación hasta que la iteración se haya completado. De lo contrario, no tiene más remedio que reiniciar la iteración para cada eliminación.

Respondida el 09/12/2008 a las 17:18
fuente por usuario

votos
0

Corregido por lo siguiente:

for(  typedefedcontainer::iterator it = m_Container.begin();
      it != m_Container.end(); 
        )
{
    if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
    {
    // If function returns false, delete object.
        m_Container.erase( it++ );
    }
    else
    { 
        ++i;
    } 

}

Cuando se elimina un elemento, todos los apuntadores quedan invalidados. Por lo tanto, usándolo ++ lo solucionamos. Gracias a quienes publicaron sugerencias.

Respondida el 09/12/2008 a las 17:30
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more