Tengo una colección de elementos en un std :: vector que se ordenan en orden descendente a partir del primer elemento. Tengo que usar un vector porque necesito tener los elementos en un trozo contiguo de memoria. Y tengo una colección que contiene muchas instancias de vectores con las características descritas (siempre ordenadas en orden descendente).vector :: erase y reverse_iterator
Ahora, a veces, cuando me entero de que tengo demasiados elementos en la mayor colección (la que sostiene estos vectores), descarto los elementos más pequeños de estos vectores de alguna manera similares a este pseudo-código:
grand_collection: collection that holds these vectors
T: type argument of my vector
C: the type that is a member of T, that participates in the < comparison (this is what sorts data before they hit any of the vectors).
std::map<C, std::pair<T::const_reverse_iterator, std::vector<T>&>> what_to_delete;
iterate(it = grand_collection.begin() -> grand_collection.end())
{
iterate(vect_rit = it->rbegin() -> it->rend())
{
// ...
what_to_delete <- (vect_rit->C, pair(vect_rit, *it))
if (what_to_delete.size() > threshold)
what_to_delete.erase(what_to_delete.begin());
// ...
}
}
Ahora, después de ejecutar este código, en what_to_delete
tengo una colección de iteradores que apuntan a los vectores originales que quiero eliminar de estos vectores (valores más pequeños en general). Recuerde, los vectores originales se ordenan antes de que lleguen a este código, lo que significa que para cualquier what_to_delete[0 - n]
no hay forma de que un iterador en la posición n - m
apunte a un elemento más al principio del mismo vector que n
, donde m > 0
.
Al borrar elementos de los vectores originales, tengo que convertir un reverse_iterator en un iterador. Para ello, me baso en C++ de 11 §24.4.1/1:
La relación entre reverse_iterator y iterador es & * (reverse_iterator (i)) == & * (i-1)
lo que significa que para eliminar un vect_rit
, utilizo:
vector.erase(--vect_rit.base());
Ahora, de acuerdo con C++ 11 estándar §23.3.6.5/3
:
iterator erase (const_iterator position); Efectos: invalida iteradores y referencias en o después del punto del borrado.
¿Cómo funciona esto con reverse_iterators? ¿Los reverse_iterators se implementan internamente con una referencia al comienzo real de un vector (vector[0]
) y transformando ese vect_rit en un iterador clásico para que luego borrarlo sea seguro? ¿O reverse_iterator usa rbegin() (que es vector[vector.size()]
) como punto de referencia y borrar todo lo que esté más alejado del índice 0 del vector aún invalidaría mi iterador inverso?
Editar:
Parece que reverse_iterator utiliza rbegin() como punto de referencia. Borrar elementos de la manera que describí me estaba dando errores sobre un iterador no deferencial después de que se eliminó el primer elemento. Mientras que al almacenar iteradores clásicos (convirtiendo a const_iterator
) al insertar en what_to_delete
funcionó correctamente.
Ahora, para referencia futura, ¿The Standard especifica qué se debe tratar como un punto de referencia en caso de un reverse_iterator de acceso aleatorio? O este es un detalle de implementación?
Gracias!
es la pregunta acerca de la carta de la norma, o alrededor de las implementaciones comunes? – Managu
@Managu - Ambos. –
Por lo que yo entiendo, no tienes/quieres usar un 'reverse_iterator' aquí. 'std :: vector' tiene iteradores de acceso aleatorio, lo que significa que puede usar un' iterator' normal que comienza en '.end()' y moverlo hacia atrás. De esta manera, no tienes que hacer mucha magia para usar '.erase()'. –