2012-07-03 9 views
12

Digamos que tengo algo de código C++:¿Por qué C++ impone tal comportamiento en la inicialización de cruces?

if (error) 
    goto exit; 
... 
// size_t i = 0; //error 
size_t i; 
i = 0; 
... 
exit: 
    ... 

entiendo que no debemos usar goto, pero aún así ¿por qué

size_t i; 
i = 0; 

compilar mientras que size_t i = 0; no?

¿Por qué el estándar impone tal comportamiento (mencionado por @SingerOfTheFall)?

Es posible transferir a un bloque, pero no de manera que puentee las declaraciones con la inicialización. Un programa que salta desde un punto donde una variable local con duración de almacenamiento automática no está en el alcance hasta un punto donde está en el alcance está mal formado a menos que la variable tenga el tipo POD (3.9) y se declare sin un inicializador.

+0

¿Qué compilador? –

+0

@Adriano: g ++ 4.1.1 –

+0

Se agregó 'language-design' porque está preguntando sobre la justificación de las decisiones de diseño para un idioma. – Kos

Respuesta

12

No puede saltar sobre la inicialización de un objeto.

size_t i = 0; 

es una inicialización, mientras

size_t i; 
i = 0; 

no lo es. El C++ Standart dice:

Es posible transferir en un bloque, pero no de una manera que no pasa por las declaraciones de inicialización. Un programa que salta desde un punto donde una variable local con una duración de almacenamiento automática no está en el alcance hasta un punto donde está en el alcance está mal formado a menos que la variable tenga el tipo POD (3.9) y se declare sin un inicializador.

+3

¿Podría explicar por qué hay un comportamiento diferente cuando son funcionalmente equivalentes? Me refiero a cuál es la razón detrás de este estándar. –

+0

Cuando inicializa una variable como esta, todavía está en alcance incluso después del salto. Eso puede causar un gran problema si intenta acceder a él, y aún más problemas al final del alcance donde debería ser destruido. Si ha saltado, la variable nunca existió, y tratar de destruirlo resultará en un bloqueo (probablemente segfault, no estoy seguro). – SingerOfTheFall

+13

La razón es que en el caso 'int i;', al definir la variable sin un inicializador, usted está diciendo "Voy a asumir la responsabilidad de garantizar que la variable se escriba antes de que se lea". El lenguaje te permite intentar eso, y si el código que sigue 'exit' usa' i', bueno, fallaste. En el caso de 'int i = 0;', el lenguaje impone que cualquier variable con un inicializador sea * siempre * inicializada antes de su uso (siempre y cuando no la use en su propio inicializador, de todos modos). La única forma sencilla en que el lenguaje puede hacer cumplir eso es prohibir su 'goto'. –

0

El motivo de la regla es que saltar sobre una inicialización deja el objeto en un estado indefinido. Cuando llegue al final de la función, la destrucción de esos objetos no inicializados podría no funcionar.

Una excepción es, obviamente, que

int i; 

deja el int sin inicializar todos modos, así que omitir que es sólo la mitad de malo.

Si desea dejar una función antes, una rápida return es una opción para evitar el goto.

Cuestiones relacionadas