2012-01-19 13 views
6

No estoy seguro de lo que está mal con este código:¿Por qué la llamada a std :: vector :: volver() estrellarse mi programa

std::vector<int> myVector(0); 

if (myVector.back() == 12) 
    myVector.push_back(12); 

Parece que volver a llamar() en un vector vacío se bloquea la programa.

No entiendo por qué está fallando? ¿Necesitamos verificar la longitud del vector antes de llamar al back()? o es posible que sea un error?

La documentación dice que, si el vector está vacío, devuelve un valor indefinido.

+1

Sospecho que equivale a que alguien te dé -1 por usar MSDN como referencia en lugar del estándar de C++. Los implementadores pueden definir mejor lo que hace su implementación en casos que el estándar dice que son UB, por lo que si MS quiere garantizar que 'back()' regresará cuando se use en un vector vacío, tienen derecho a hacerlo. Si está utilizando MSVC++, tiene derecho a leer su documentación. Pero podría ser -1 por no darse cuenta de que el uso de un "valor indefinido" de cualquier manera, puede causar un bloqueo. –

+0

@SteveJessop Creo que MSDN es la implementación del estándar C++. Pero me parece raro que llamar a un método en un elemento válido (hasta donde sé que un vector vacío es un elemento válido) interrumpe mi programa. Bueno, si el estándar lo dice, que así sea :) – MBen

+1

MSVC++ es * una * implementación de (aproximadamente) el estándar C++. Otras implementaciones se comportan de manera diferente, si el estándar no establece el comportamiento. La razón por la que el estándar no define la invocación 'back()' en un vector vacío es para que las implementaciones no necesiten un código de caso especial para él. Por lo tanto, pueden elegir ser más rápidos de lo que serían si tuvieran que verificar si el vector estaba vacío o no, y hacer cosas diferentes en casos diferentes. Serán propensos a bloquearse (o empeorar) cuando haces algo mal. Puede parecer extraño, pero es una compensación hecha como parte del diseño del lenguaje. –

Respuesta

13

¿necesitamos verificar la longitud del vector antes de volver a llamar()?

En una palabra: sí. Este es su error, su vector está vacío, por lo que no hay elemento "atrás".

La documentación debe decir (si dice nada en absoluto) que llamar back() en un vector vacío provoca un comportamiento indefinido , no es que devuelve un valor no definido.

+0

Por alguna razón, MSDN dice "el valor de retorno no está definido" (http://msdn.microsoft.com/en-us/library/0532x4xk%28v=vs.80%29.aspx). Pero también dice: "Al compilar con _SECURE_SCL 1, se producirá un error de tiempo de ejecución si intenta acceder a un elemento en un vector vacío". No sé (a) por qué MS se refiere a una referencia como un "valor", o (b) cómo cuadran la noción de un "valor indefinido" con la noción de una referencia que da como resultado un error de tiempo de ejecución cuando se utiliza . Pero ese error de tiempo de ejecución bien podría ser lo mismo que el que pregunta describe como "estrellarse". –

+0

Todavía pienso que es extraño que llamar a un método en un elemento válido cuelgue mi programa. – MBen

+0

@MBen: Pero no hay elementos en su vector; es una condición previa de 'back()' que haya al menos un elemento en su vector. Esa es la forma en que se define la interfaz. Debe asegurarse de que su entrada cumpla con la condición previa antes de intentar llamar 'back()'. –

5

C++ 11 estándar dice esto:

23.3.2.8/3

El e ff ect de llamar frontal() o hacia atrás() para una matriz de tamaño cero es fi unde nida.

Dado que el comportamiento no está definido, todo puede pasar. Tuviste la suerte de tener un accidente.

+0

No creo tener suerte, se siente raro que llamar a un método en un válido valor bloquea mi programa. – MBen

+3

@MBen Tener un programa bloqueado en UB es bueno, porque es fácil detectar el error. Cuando a veces funciona y otras no, es muy difícil encontrar el error. –

+0

Estoy de acuerdo. Solo necesito asegurarme de que el vector tenga elementos :-) – MBen

Cuestiones relacionadas