2009-09-02 11 views
8

Dopo aver provato la mia mano in Perl e un po 'di C, sto cercando di imparare il C++ e già sono impantanato dai dettagli e dalle insidie. Considera questo: -C++: semantica confusionaria delle dichiarazioni

int x = 1; 
{ 
    int x = x; // garbage value of x 
} 
int const arr = 3; 
{ 
    int arr[arr]; // i am told this is perfectly valid and declares an array of 3 ints !! 
} 

Huh, perché la differenza?

Per chiarire: l'uso dello stesso nome è valido in un caso e non valido in un altro.

+1

Può chiarire la tua domanda? A quale differenza ti riferisci? – trshiv

+0

Io uso lo stesso nome quando provo cose semplici come int x = x, non è valido, provo a farlo per costrutti complessi come int arr [arr] è valido. Mi confonde –

+0

Forse questo è ovvio, ma indipendentemente dal fatto che il codice sopra abbia un senso per il compilatore, è difficile da comprendere per un essere umano, quindi è improbabile che lo si veda nel codice esistente e poco saggio metterlo in proprio. – flies

risposta

14

Benvenuti nell'universo di C++! Per la tua domanda, la risposta si trova in un concetto chiamato "Point of declaration".

>>int x = 1; 
>>{ int x = x; } // garbage value of x 

Dalla sezione: -3.3.1.1 (C++ Draft Standard) Il punto di dichiarazione per un nome è immediatamente dopo la sua completa dichiaratore e prima della sua inizializzazione (se presente), ad eccezione di quanto indicato di seguito.

int x = 12; 
{ int x = x; } 

Qui; il 'operator =' è l'inizializzatore. Puoi dire che il punto di dichiarazione per 'x' non è ancora stato raggiunto, quindi il valore di 'x' è indeterminato.

>>int const arr = 3; 
>>{ int arr[arr]; } // i am told this is perfectly valid and declares an array of 3 ints !! 

Perché? Dalla sezione: -3.3.1.4 (Bozza standard C++) Un nome non locale rimane visibile fino al punto di dichiarazione del nome locale che lo nasconde. Qui il punto di dichiarazione è raggiunto a ';' carattere. vale a dire in modo viene utilizzato il valore visibile precedente di 'arr' = 3.

Inoltre, si potrebbe desiderare di sapere che vale quanto segue: -

const int e = 2; 
{ enum { e = e }; } // enum e = 2 

Dalla sezione: -Capitolo-3.3.1.4 (C++ Standard Draft): - Il punto di dichiarazione per un enumeratore è immediatamente successivo alla definizione del suo enumeratore.

Ma, non farlo

const int Spades = 1, Clubs = 2, Hearts = 3, Diamonds = 4; 
enum Suits 
{ 
    Spades = Spades,  // error 
    Clubs,    // error 
    Hearts,    // error 
    Diamonds    // error 
}; 

Perché? Poiché gli enumeratori vengono esportati nell'ambito di inclusione dell'enumerazione. Nell'esempio sopra, vengono dichiarati gli enumeratori Spades, Clubs, Hearts e Diamonds. Poiché gli enumeratori vengono esportati nell'ambito di inclusione, vengono considerati con ambito globale. Gli identificatori nell'esempio sono già definiti nell'ambito globale. Quindi è un errore.

Per ulteriori dettagli e problemi (:-)), consultare la sezione 3.3 "Regioni dichiarative e ambiti" della bozza Standard C++, se interessati è possibile ottenere il pdf da here (http://www.research.att.com/~bs/SC22-N-4411.pdf).

+1

Grazie per la spiegazione, ma perché è necessario essere così complessi? –

+0

Penso "Puoi dire che il punto di dichiarazione per 'x' non è ancora stato raggiunto, quindi il valore di 'x' è indeterminato" è sbagliato. Il punto di dichiarazione è già stato raggiunto, e questo è il motivo per cui "x" è indeterminato, perché è già dichiarato, ma non ancora inizializzato. – Gorpik

+3

Il motivo per cui le regole devono essere complesse è che i dichiaratori C++ * sono * complessi. Ci sono un sacco di capacità in là, combinate con un sacco di cruft di retrocompatibilità, nessuna interruzione netta dalla sua cronologia C (dove questa roba non è stata specificata in modo abbastanza formale e casi come questo erano spesso fino all'implementatore del compilatore), e tu ottieni le regole standard del C++. –

7

In primo luogo, nel mondo reale non si dovrebbe usare né perché è confuso, e anche pochi secondi per capire questo punto fine è troppo spreco.

rottami il resto della mia risposta - Abhay già capito bene, e di gran lunga più in dettaglio :)

+1

Pur non essendo una vera risposta alla domanda, ottiene un revival per il pragmatismo. –

+0

+1 Sono d'accordo anche con il tuo pragmatismo :-). Ma immagino che l'O.P. come studente sia stato colto di sorpresa dalla natura del trabocchetto. – Abhay

+1

+1 Semplicemente non inserire mai tale codice nei sistemi di produzione. – sharptooth

Problemi correlati