2012-03-06 32 views

Respuesta

16

La norma no lo define del todo, pero v.erase(q) se define como "Borra el elemento apuntado por q" en [sequence.reqmts]. Esto significa que q realmente debe apuntar a un elemento, que no lo hace el iterador final. Pasar al final del iterador es un comportamiento indefinido.

Por desgracia, tiene que escribir:

auto it = std::find(...); 
if (it != <the part of ... that specifies the end of the range searched>) { 
    v.erase(it); 
} 

Por supuesto, se podría definir:

template typename<Sequence, Iterator> 
Iterator my_erase(Sequence &s, Iterator it) { 
    if (it == s.end()) return it; 
    return s.erase(it); 
} 

my_erase(v, std::find(v.begin(), v.end(), whatever)); 

c.erase() en una asociativos vuelve contenedores void, por lo que la generalización de esta plantilla para todos los contenedores que necesita algo de acción -> decltype.

+0

+1 para referencia estándar. –

+0

[documentos] (http://www.cplusplus.com/reference/vector/vector/erase/) dice que "borrar elementos en posiciones distintas al vector final hace que el contenedor se reubique ...". Parece que dejar de end() como parámetro. Y en ninguna parte se dijo lo contrario explícitamente. No me gusta esto ... – Pavel

+1

@Pavel: luego tendrás que comentarlo con los autores de "cplusplus.com". Es * no * la documentación de C++, el estándar es la documentación de C++. Pero define 'position' como" Iterator apuntando a un solo elemento ". Un iterador final no apunta a un solo elemento. –

6

¿Has probado esto?

v.erase(remove_if(v.begin(), v.end(), (<your criteria>)), v.end()); 
+1

-1: Los algoritmos no eliminan elementos de los contenedores. –

+0

La falta de otras respuestas correctas no hace que su respuesta sea correcta. –

+4

No sé por qué esto se ha votado negativamente (aparte de tal vez una respuesta inicial que ha sido editada). El código tal como está es correcto. –

23

Borrado end() (o para el caso, incluso buscando en el blanco de end()) es un comportamiento indefinido. El comportamiento indefinido puede tener cualquier comportamiento, incluido "solo trabajo" en su plataforma. Eso no significa que deberías estar haciéndolo; todavía es un comportamiento indefinido, y voy a morderte de la peor manera cuando menos lo esperes más adelante.

Dependiendo de lo que esté haciendo, es posible que desee considerar set o unordered_set en lugar de vector aquí.

+0

gracias, sé lo que es UB, solo quería saber, ¿es realmente UB? – RiaD

+0

@RiaD: Sí, es UB. La solución es muy simple, sin embargo, simplemente verifique antes de borrar: '{auto it = v.find (x); if (it! = x.end()) {v.erase (it); }} ' –

+0

Pregunta para ti @Billy. Por curiosidad, ¿fin() - 1 funciona? ¿Cómo es esto diferente de pop_back()? – Gaffi