2011-05-31 10 views
19

int foo = foo; compila. ¿Qué parte del estándar C++ permite esto?Referencia estándar para int foo = foo

+0

Relacionados: http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 –

+0

Consulte también [¿La inicialización conlleva la conversión lvalue-to-rvalue? Es 'int x = x;' UB?] (Http://stackoverflow.com/q/14935722/1708801) y [¿Ha cambiado el estándar de C++ con respecto al uso de valores indeterminados y comportamiento indefinido en C++ 14?] (http://stackoverflow.com/q/23415661/1708801) –

Respuesta

26

3.3.1 Punto de declaración [basic.scope.pdecl]

El punto de declaración para un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si existe),

El comportamiento está bien definido si la declaración está en el alcance del archivo. Si tiene la declaración en el alcance de la función y si usa foo más adelante [que se inicializaría a algún valor no especificado en ese caso], el comportamiento sería indefinido.

+4

Haría +1 pero ha omitido mencionar que el programa del OP tiene un comportamiento indefinido y _no debe usarse_. –

+5

@Tomalak: El código * podría * tener UB, pero no necesariamente. El OP parece plenamente consciente de que no es algo que realmente deba usarse, y siente curiosidad sobre el punto puramente académico de por qué se compila en absoluto. –

+2

@Jerry: hada nuff. –

21

Esto?

int main() { 
    int foo = foo; 
} 

El objeto foo existe después de la =, según [basic.scope.pdecl]:

El punto de declaración para un nombre es inmediatamente después de su completa declarador (cláusula 8) y antes de su inicializador (si corresponde).

Sin embargo, el programa en su conjunto no está definido, debido a que utiliza (en el lado derecho) un valor no inicializado:

int x = x; Aquí [..] x se inicializa con su propio (indeterminado) valor.

Y:

Aunque "inferido y malos especificado por" por la norma, an lvalue-to-rvalue conversion is performed on the RHS expression foo.

Y ([conv.lval]):

Un lvalue (3,10) de un no-función, tipo no matriz T se puede convertir en un rvalue. Si T es un tipo incompleto, un programa que necesita esta conversión está mal formado. Si el objeto al que se refiere la lvalue es no un objeto de tipo T y no es un objeto de un tipo derivado de T, o si el objeto es inicializado, un programa que requiere esta conversión tiene comportamiento indefinido .

Con los niveles de advertencia adecuados, you will get told about it; sin embargo, los programas que invocan Comportamiento no definido pueden compilarse. Simplemente pueden hacer cualquier cosa cuando los ejecutas.


O, ¿qué tal esto?

int foo = foo;  
int main() {} 

Observe que foo es un operador "global". Estos son cero-inicializado como un primer paso, de acuerdo con [basic.start.init]:

objetos con una duración de almacenamiento estático (3.7.1) serán cero inicializa (8.5) antes de cualquier otro inicialización tiene lugar.

Así obtendrá un int foo con valor 0; es válida, en este punto, como por [basic.scope.pdecl] anteriormente, y según [stmt.decl]:

El cero de inicialización (8.5) de todos los objetos locales con estática duración de almacenamiento (3.7.1) se realiza antes de cualquier otra inicialización tiene lugar. [..]

A continuación, el valor-inicializar a foo (sí), es decir 0.

Esto está bien definido ... si un poco críptico.


En aras de la exhaustividad, aquí hay un tercer y último caso:

int foo = 42; 
int main() { 
    int foo = foo; 
} 

Lamentablemente, this is the same as the first case. Dado que el foo local ya está declarado y en el alcance en el momento en que se evalúa el inicializador, el inicializador usa el foo local y aún está atascado con el Comportamiento no definido. El global foo no se usa.

+1

OTOH, si es un global, el comportamiento está definido. –

+0

@Jerry: no hay globales en mi programa. Si hay variables globales en el programa del OP (o si su declaración 'foo' ocurre en el ámbito del espacio de nombres), necesita indicar esto porque cambia completamente la pregunta. –

+0

@Jerry: OK. Agregaré una cláusula para ese caso, entonces, también. –

Cuestiones relacionadas