int foo = foo;
compila. ¿Qué parte del estándar C++ permite esto?Referencia estándar para int foo = foo
Respuesta
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.
Haría +1 pero ha omitido mencionar que el programa del OP tiene un comportamiento indefinido y _no debe usarse_. –
@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. –
@Jerry: hada nuff. –
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.
OTOH, si es un global, el comportamiento está definido. –
@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. –
@Jerry: OK. Agregaré una cláusula para ese caso, entonces, también. –
- 1. ¿Qué significa esto? int foo = foo + 4;
- 2. static_cast <int> (foo) vs. (int) foo
- 3. var foo = foo || alerta (foo);
- 4. Foo f = Foo(); // no hay función de coincidencia para la llamada a 'Foo :: Foo (Foo)' ... ¿eh?
- 5. ¿Hay alguna diferencia entre [& foo] {...} captura y [foo] {...} captura si 'foo' es una variable de referencia?
- 6. char * foo vs char * foo
- 7. Foo no se puede convertir a Foo
- 8. 'var foo = función ...' y 'la función foo() ...'
- 9. Scala: 'foo def = {1}' vs 'foo def {1}'
- 10. Absoluto ("/ foo") y relativo ("../foo") nombres de archivo. ¿Cómo se llama la categoría "foo"?
- 11. Diferencia entre "struct foo *" y "foo *" donde foo es una estructura?
- 12. ¿Por qué Amazon S3 no sirve automáticamente /foo/index.html cuando solicito/foo o/foo /?
- 13. Es Foo * f = new Foo buen código de C++
- 14. ¿De qué sirve decir "#define FOO FOO" en C?
- 15. ¿Cuándo os.environ ['foo'] no coincide con os.getenv ('foo')?
- 16. orden de operaciones C - foo() + barra() - ¿debe llamarse foo antes de la barra?
- 17. jQuery $ each (arr, foo) contra $ (arr) .Cada (foo)
- 18. Diferencia entre clase foo y clase foo (objeto) en Python
- 19. R: apt-get install r-cran-foo vs. install.packages ("foo")
- 20. polimorfismo C++ ((X *) y) -> foo() vs ((X) * y) .foo()
- 21. ¿Hay alguna diferencia entre "foo is None" y "foo == None"?
- 22. ¿Qué es "x && foo()"?
- 23. ¿qué quiere decir FOO?
- 24. Para foo bar, o no para foo bar: esa es la pregunta
- 25. La conversión de "foo <T>" a "foo const <const T>" - C++
- 26. En Java, ¿por qué la llamada foo() no es ambigua dado 2 métodos de varags foo (int ... ints) y foo (objeto ... objetos)?
- 27. La referencia a la entidad "foo" debe terminar con ';' delimitador
- 28. selector CSS para "foo que contiene barra"?
- 29. ¿Para qué es el proyecto de PS ($ Foo) en mi solución $ Foo ATL?
- 30. ¿Por qué no funciona "git log - foo" para el archivo eliminado foo?
Relacionados: http://stackoverflow.com/questions/5450633/c-what-does-this-mean-int-foo-foo-4 –
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) –