2012-07-03 4 views
12

Diciamo che ho un po 'di codice C++:Perché C++ applica questo comportamento durante l'inizializzazione incrociata?

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

ho capito che non dovremmo usare goto, ma ancora Perché

size_t i; 
i = 0; 

compilare mentre size_t i = 0; non lo fa?

Perché un tale comportamento è applicato dallo standard (citato da @SingerOfTheFall)?

È possibile trasferire in un blocco, ma non in modo che ignori le dichiarazioni con l'inizializzazione. Un programma che salta da un punto in cui una variabile locale con durata di archiviazione automatica non è nello scope in un punto in cui è in ambito non formattato a meno che la variabile non abbia il tipo POD (3.9) e sia dichiarata senza inizializzatore.

+0

Quale compilatore? –

+0

@Adriano: g ++ 4.1.1 –

+0

Aggiunto 'language-design' perché stai chiedendo informazioni sulle decisioni di progettazione per una lingua. – Kos

risposta

12

Non è possibile saltare l'inizializzazione di un oggetto.

size_t i = 0; 

è un'inizializzazione, mentre

size_t i; 
i = 0; 

non è. Il C++ Standart dice:

È possibile trasferire in un blocco, ma non in modo che aggira le dichiarazioni con l'inizializzazione. Un programma che salta da un punto in cui una variabile locale con durata dell'archiviazione automatica non è nell'ambito di un punto in cui è nell'ambito dell'ambito è mal formata a meno che la variabile non abbia il tipo POD (3.9) e sia dichiarata senza un inizializzatore.

+3

Potresti spiegare perché c'è un comportamento diverso quando sono funzionalmente equivalenti? Voglio dire qual è la logica dietro questo standard. –

+0

Quando si inizializza una variabile come questa, è ancora in ambito anche dopo il salto. Ciò potrebbe causare grossi problemi se tenterai di accedervi, e ancora più problemi alla fine dell'ambito in cui dovrebbe essere distrutto. Se sei saltato sopra, la variabile non è mai esistita, e provando a distruggerla si verificherà un crash (probabilmente segfault, non sono sicuro). – SingerOfTheFall

+13

La logica è che nel caso "int i;", definendo la variabile senza un inizializzatore, stai dicendo "Mi assumerò la responsabilità di assicurare che la variabile sia scritta prima che venga letta". La lingua ti permette di tentare ciò, e se il codice che segue 'exit' usa' i', beh, hai fallito. Nel caso di 'int i = 0;', il linguaggio impone che qualsiasi variabile con un inizializzatore sia * sempre * inizializzata prima dell'uso (a condizione che non lo si usi nel proprio inizializzatore, comunque). L'unico modo semplice in cui la lingua può imporre è vietare il tuo 'goto'. –

0

La ragione per la regola è che salta sopra un'inizializzazione lascia l'oggetto in uno stato indefinito. Quando arrivi alla fine della funzione, distruggere quegli oggetti non inizializzati potrebbe non funzionare.

L'unica eccezione è, ovviamente, che

int i; 

lascia il int non inizializzato in ogni caso, in modo da saltare la che è solo la metà male.

Se si desidera abbandonare anticipatamente una funzione, è possibile utilizzare lo return per evitare lo goto.