Pregunta

Supongamos que tengo un hash_map y un código como

// i is an iterator
i = hash_map.erase(i)

Pero el STL de GCC no devuelve el iterador en borrado, sino un vacío. Ahora es un código como

hash_map.erase(i++)

seguro (es decir, no invalida el iterador o cualquier otra cosa inesperada o desagradable)? Tenga en cuenta que este es un hash_map.

¿Fue útil?

Solución

Sí, esto es seguro, porque el valor de i se habrá establecido en el siguiente valor, antes de que se borre el valor actual.

Según la la validación de la documentación de la SGI sobre contenedores con hash no se produce para elementos borrados, ni siquiera para cambiar el tamaño (no hay información sobre si las inserciones causan el cambio de tamaño, así que tenga cuidado, lo admito como una posibilidad) --- pero en el último caso, el orden de iteración cambiará. Pero esto no se aplica aquí, a menos que haga un esfuerzo para cambiar el tamaño del contenedor durante el recorrido o algo así. :-)

Otros consejos

Puede encapsular el borrado para proporcionar la misma interfaz para todos los contenedores que utiliza:

namespace detail {
template<typename Container, typename R>
struct SelectErase {
  // by default, assume the next iterator is returned
  template<typename Iterator>
  Iterator erase(Container& c, Iterator where) {
    return c.erase(where);
  }
};
// specialize on return type void
template<typename Container>
struct SelectErase<Container, void> {
  template<typename Iterator>
  Iterator erase(Container& c, Iterator where) {
    Iterator next (where);
    ++next;
    c.erase(where);
    return next;
  }
};

template<typename I, typename Container, typename R>
SelectErase<Container,R> select_erase(R (Container::*)(I)) {
  return SelectErase<Container,R>();
}
} // namespace detail

template<typename Container, typename Iterator>
Iterator erase(Container& container, Iterator where) {
  return detail::select_erase<Iterator>(&Container::erase).erase(container, where);
}

Esto requiere:

  1. c.erase devuelve el iterador para el siguiente elemento. Así es como funcionan el vector, el deque y la lista.
  2. c.erase devuelve void y no invalida el siguiente iterador. Así es como funcionan el mapa, el conjunto y (no-stdlib) hash_map.

Odio llover en el desfile, pero no creo que lo que propongas sea seguro.

i ++ es el operador de incremento posterior, lo que significa que i se incrementa después de la llamada para borrar. Pero borrar invalida todos los iteradores que apuntan al elemento que se está borrando. Entonces, cuando se incrementa, ya no es válido.

Si tienes suerte, puede funcionar correctamente por accidente hasta que un día ya no funcione.

Por lo que yo sé, no hay manera de evitar esto, pero algo como:

// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top