Atualizado, veja abaixo!
Ouvi e li que o C ++ 0x permite que um compilador imprima "Olá" para o seguinte trecho
#include <iostream>
int main() {
while(1)
;
std::cout << "Hello" << std::endl;
}
Aparentemente, tem algo a ver com threads e recursos de otimização. Parece-me que isso pode surpreender muitas pessoas.
Alguém tem uma boa explicação de por que isso era necessário? Para referência, o rascunho mais recente do C ++ 0x diz em6.5/5
Um loop que, fora da instrução for-init no caso de uma instrução for,
- não faz chamadas para funções de E / S da biblioteca e
- não acessa ou modifica objetos voláteis e
- não executa operações de sincronização (1.10) ou operações atômicas (Cláusula 29)
pode ser assumido pela implementação para terminar. [Nota: Pretende-se permitir transformações do compilador, como remoção de loops vazios, mesmo quando a terminação não puder ser comprovada. - nota final]
Editar:
Este artigo esclarecedor diz sobre o texto dos Padrões
Infelizmente, as palavras "comportamento indefinido" não são usadas. No entanto, sempre que o padrão diz "o compilador pode assumir P", está implícito que um programa que possui a propriedade not-P possui semântica indefinida.
Isso está correto e o compilador pode imprimir "Tchau" para o programa acima?
Há um tópico ainda mais perspicaz aqui , que trata de uma alteração análoga a C, iniciada pelo Guy que fez o artigo acima. Entre outros fatos úteis, eles apresentam uma solução que parece se aplicar também ao C ++ 0x ( atualização : isso não funcionará mais com o n3225 - veja abaixo!)
endless:
goto endless;
Um compilador não pode otimizar isso, ao que parece, porque não é um loop, mas um salto. Outro cara resume a alteração proposta em C ++ 0x e C201X
Ao escrever um loop, o programador está afirmando quer que o loop faz algo com o comportamento visível (executa E / S, acessa objetos voláteis, ou sincronização executa ou operações atômicas), ou que, eventualmente, termina. Se eu violar essa suposição escrevendo um loop infinito sem efeitos colaterais, minto para o compilador e o comportamento do meu programa é indefinido. (Se eu tiver sorte, o compilador poderá me avisar.) A linguagem não fornece (não fornece mais?) Uma maneira de expressar um loop infinito sem comportamento visível.
Atualização em 3.1.2011 com n3225: o Comitê mudou o texto para 1.10 / 24 e diz
A implementação pode assumir que qualquer encadeamento acabará por executar um dos seguintes procedimentos:
- terminar,
- faça uma chamada para uma função de E / S da biblioteca,
- acessar ou modificar um objeto volátil, ou
- executar uma operação de sincronização ou uma operação atômica.
O goto
truque não vai mais funcionar!
int x = 1; for(int i = 0; i < 10; ++i) do_something(&i); x++;
para for(int i = 0; i < 10; ++i) do_something(&i); int x = 2;
? Ou possivelmente o contrário, com x
a inicialização 2
antes do loop. Ele pode dizer do_something
que não se importa com o valor de x
, portanto é uma otimização perfeitamente segura, se do_something
não fizer com que o valor i
seja alterado de forma que você termine em um loop infinito.
main() { start_daemon_thread(); while(1) { sleep(1000); } }
pode sair imediatamente, em vez de executar meu daemon em um encadeamento em segundo plano?
while(1) { MyMysteriousFunction(); }
deve ser compilável independentemente, sem conhecer a definição dessa função misteriosa, certo? Então, como podemos determinar se ele faz chamadas para qualquer função de E / S da biblioteca? Em outras palavras: certamente que a primeira bala poderia ser redigida não faz chamadas para funções .