Edit: Lo sentimos, la versión original de esto era incorrecta. Fijo.
Esto es lo que está pasando. Su aportación a remove_if
es:
1 2 3 4 5 6
^ ^
begin end
y el algoritmo remove_if
mira a todos los números entre begin
y end
(incluyendo begin
, pero excluyendo end
), y elimina todos los elementos entre que coincidan con su predicado. Así que después de remove_if
carreras, su vector se parece a esto
1 2 3 ? 5 6
^^
begin new_end
Dónde ?
es un valor que no creo es determinista, aunque si se garantiza que sea algo sería 4
. Y new_end
, que apunta al nuevo extremo de la secuencia de entrada que le dio, con los elementos coincidentes ahora eliminados, es lo que devuelve std::remove_if
. Tenga en cuenta que std::remove_if
no toca nada más allá de la subsecuencia que le diste. Esto podría tener más sentido con un ejemplo más extendido.
decir que esta es su entrada:
1 2 3 4 5 6 7 8 9 10
^ ^
begin end
Después std::remove_if
, se obtiene:
1 2 3 5 7 ? ? 8 9 10
^ ^
begin new_end
pensar en esto por un momento. Lo que ha hecho es eliminar el 4 y el 6 de la subsecuencia, y luego desplazar todo hacia abajo en la subsecuencia hacia abajo para completar los elementos eliminados, y luego mover el iterador end
al nuevo final de la misma subsecuencia. El objetivo es satisfacer el requisito de que la secuencia (begin
, new_end
] que produce sea la misma que la subsecuencia (begin
,) que transfirió, pero con ciertos elementos eliminados. Cualquier cosa que exceda el end
que haya pasado. se deja intacto.
lo que quiere deshacerse de, a continuación, es todo lo que entre el iterador final que fue devuelto, y el iterador final original, que le dio. Estos son los valores ?
"basura". Así su llamada de borrado debería ser:
ints.erase(it, ints.begin()+4);
La llamada a erase
que acaba de borrar todo más allá del final de la subsecuencia en la que realizó la eliminación, que no es lo que desea aquí.
Lo que lo hace complicado es que el algoritmo remove_if
en realidad no llama al erase()
, o cambia el tamaño del vector en cualquier punto. Simplemente cambia elementos y deja algunos elementos "basura" después del final de la subsecuencia que solicitó que procesara. Esto parece tonto, pero la razón por la que STL lo hace de esta manera es evitar el problema con los iteradores invalidados que trajo el doublep (y poder ejecutar cosas que no son contenedores STL, como matrices en bruto).
Buenos gráficos :) Bueno, no pensé que fuera necesario omitir la llamada a erase(), pero el depurador me está dando un comportamiento extraño después de eliminar_if(), así que me preguntaba si estaba haciendo algo mal o este tipo de uso no es correcto (usando listas entonces, como dijo doublep) –
Bueno, tu versión extendida realmente me aclara las cosas. Voy a probar tus sugerencias y dar tu opinión pronto –