Actualizado, ver abajo!
He escuchado y leído que C ++ 0x permite que un compilador imprima "Hola" para el siguiente fragmento
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Aparentemente tiene algo que ver con hilos y capacidades de optimización. Sin embargo, me parece que esto puede sorprender a muchas personas.
¿Alguien tiene una buena explicación de por qué esto era necesario permitir? Como referencia, el borrador más reciente de C ++ 0x dice en6.5/5
Un bucle que, fuera de la declaración for-init en el caso de una declaración for,
- no realiza llamadas a las funciones de E / S de la biblioteca, y
- no accede ni modifica objetos volátiles, y
- no realiza operaciones de sincronización (1.10) u operaciones atómicas (Cláusula 29)
la implementación puede suponer que termina. [Nota: Esto está destinado a permitir transformaciones del compilador, como la eliminación de bucles vacíos, incluso cuando no se pueda probar la terminación. - nota final]
Editar:
Este artículo perspicaz dice sobre ese texto de Normas
Lamentablemente, las palabras "comportamiento indefinido" no se utilizan. Sin embargo, cada vez que el estándar dice "el compilador puede asumir P", está implícito que un programa que tiene la propiedad no-P tiene una semántica indefinida.
¿Es correcto y el compilador puede imprimir "Bye" para el programa anterior?
Aquí hay un hilo aún más perspicaz , que trata sobre un cambio análogo a C, iniciado por el tipo que hizo el artículo vinculado anterior. Entre otros datos útiles, presentan una solución que parece aplicarse también a C ++ 0x ( Actualización : esto ya no funcionará con n3225, ¡vea a continuación!)
endless:
goto endless;
Un compilador no puede optimizar eso, parece, porque no es un bucle, sino un salto. Otro tipo resume el cambio propuesto en C ++ 0x y C201X
Al escribir un bucle, el programador está afirmando ya sea que el bucle hace algo con el comportamiento visible (realiza de E / S, accesos objetos volátiles, o la sincronización realiza o operaciones atómicas), o que eventualmente termina. Si violo esa suposición escribiendo un bucle infinito sin efectos secundarios, le estoy mintiendo al compilador y el comportamiento de mi programa no está definido. (Si tengo suerte, el compilador podría advertirme al respecto). El lenguaje no proporciona (¿ya no proporciona?) Una forma de expresar un bucle infinito sin un comportamiento visible.
Actualización el 3.1.2011 con n3225: el Comité movió el texto al 1.10 / 24 y dijo
La implementación puede suponer que cualquier hilo eventualmente hará uno de los siguientes:
- Terminar,
- hacer una llamada a una función de E / S de la biblioteca,
- acceder o modificar un objeto volátil, o
- realizar una operación de sincronización o una operación atómica.
¡El goto
truco ya no funcionará!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
en for(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
? O posiblemente al revés, con x
ser inicializado a2
antes del bucle. Puede decir que do_something
no le importa el valor de x
, por lo que es una optimización perfectamente segura, si do_something
no hace que el valor de i
cambie de modo que termine en un bucle infinito.
main() { start_daemon_thread(); while(1) { sleep(1000); } }
podría salir inmediatamente en lugar de ejecutar mi demonio en un hilo de fondo?
while(1) { MyMysteriousFunction(); }
debe ser compilable independientemente sin conocer la definición de esa misteriosa función, ¿verdad? Entonces, ¿cómo podemos determinar si realiza llamadas a alguna función de E / S de la biblioteca? En otras palabras: seguramente esa primera viñeta podría estar redactada no hace llamadas a funciones .