2009-09-02 14 views
8

Después de probar mi mano en Perl y un poco de C, estoy tratando de aprender C++ y ya estoy empantanado por los detalles y las trampas. Considere esto: -C++: semántica de declaración confusa

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, ¿por qué la diferencia?

Para aclarar: El uso del mismo nombre es válido en un caso y no es válido en otro.

+1

Puede aclarar su pregunta? ¿A qué diferencia te refieres? – trshiv

+0

Utilizo el mismo nombre al intentar cosas simples como int x = x, no es válido, intento hacerlo para construcciones complejas como int arr [arr] its valid. Me confunde. –

+0

Quizás esto sea obvio, pero independientemente de si el código anterior tiene sentido para el compilador, es difícil de entender para un humano, por lo que es poco probable que lo veas en el código existente y no es prudente ponerlo en el tuyo. – flies

Respuesta

14

¡Bienvenido al universo de C++! Para su pregunta, la respuesta se encuentra en un concepto llamado 'Punto de declaración'.

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

De Sección: -3.3.1.1 (C++ Proyecto de Norma) El punto de la declaración de un nombre es inmediatamente después de su completa declarador y antes de su inicializador (si lo hay), excepto como se indica a continuación.

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

Aquí; el 'operador =' es el inicializador. Puede decir que aún no se ha alcanzado el punto de declaración para 'x', por lo que el valor de 'x' es indeterminado.

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

¿Por qué? De la sección: -3.3.1.4 (Borrador estándar de C++) Un nombre no local permanece visible hasta el momento de la declaración del nombre local que lo oculta. Aquí el punto de declaración se alcanza en ';' personaje. es decir, lo que el valor visible a principios de 'arr' se utiliza = 3.

También, usted puede desear saber que lo siguiente es válido: -

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

De Sección: -Capítulo-3.3.1.4 (Proyecto estándar de C++): - El punto de declaración de un enumerador es inmediatamente posterior a su definición de enumerador.

Pero, no haga esto

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

¿Por qué? Porque los enumeradores se exportan al alcance de la enumeración. En el ejemplo anterior, se declaran los enumeradores Picas, Tréboles, Corazones y Diamantes. Debido a que los enumeradores se exportan al ámbito adjunto, se considera que tienen alcance global. Los identificadores en el ejemplo ya están definidos en el alcance global. Entonces es un error.

Para detalles adicionales y dificultades (:-)), consulte en la sección 3.3 'Regiones declarativas y ámbitos' del Estándar Draft C++, si está interesado puede obtener el pdf del here (http://www.research.att.com/~bs/SC22-N-4411.pdf).

+1

Gracias por la explicación, pero ¿por qué tiene que ser tan complejo? –

+0

Creo que "Puedes decir que el punto de declaración para 'x' aún no se ha alcanzado, por lo que el valor de 'x' es indeterminado" es incorrecto. El punto de declaración ya se ha alcanzado, y esta es la razón por la cual 'x' es indeterminado, porque ya está declarado, pero aún no se ha inicializado. – Gorpik

+3

La razón por la que las reglas deben ser complejas es que los declaradores C++ * son * complejos. Hay mucha capacidad allí, combinada con una gran cantidad de compatibilidad con versiones anteriores, sin una interrupción limpia de su historial de C (donde esto no se especificó de manera tan formal y los casos de borde como este a menudo correspondían al implementador del compilador), y usted obtener las reglas estándar de C++. –

7

En primer lugar, en el mundo real no debe usar ninguno porque es confuso, e incluso unos pocos segundos para entender este punto fino es demasiado desperdicio.

chatarra el resto de mi respuesta - Abhay ya lo hizo bien, y con mucho más detalle :)

+1

Si bien no es una respuesta real a la pregunta, obtiene un voto favorable para el pragmatismo. –

+0

+1 Estoy de acuerdo con tu pragmatismo también :-). Pero supongo que el O.P. como estudiante fue tomado por sorpresa con la naturaleza de la trampa. – Abhay

+1

+1 Simplemente nunca coloque dicho código en los sistemas de producción. – sharptooth