Qual é o significado de incluir
ios_base::sync_with_stdio(false);
cin.tie(NULL);
em programas C ++?
Nos meus testes, isso acelera o tempo de execução, mas há um caso de teste que eu deveria me preocupar em incluir isso?
As duas instruções sempre precisam estar juntas ou a primeira é suficiente, ou seja, é ignorar cin.tie(NULL)
?
Além disso, é permitido usar comandos simultâneos de C e C ++ se seu valor tiver sido definido como false
?
https://www.codechef.com/viewsolution/7316085
O código acima funcionou bem, até que eu usei scanf/printf
em um programa C ++ com o valor como true
. Nesse caso, ocorreu uma falha de segmentação. Qual poderia ser a explicação possível para isso?
Respostas:
As duas chamadas têm significados diferentes que nada têm a ver com desempenho; o fato de acelerar o tempo de execução é (ou pode ser ) apenas um efeito colateral. Você deve entender o que cada um deles faz e não os incluir cegamente em todos os programas, porque eles parecem uma otimização.
Isso desativa a sincronização entre os fluxos padrão C e C ++. Por padrão, todos os fluxos padrão são sincronizados, o que, na prática, permite misturar E / S no estilo C e C ++ e obter resultados esperados e sensíveis. Se você desativar a sincronização, os fluxos C ++ poderão ter seus próprios buffers independentes, o que torna uma mistura de E / S nos estilos C e C ++.
Lembre-se também de que os fluxos C ++ sincronizados são seguros para threads (a saída de diferentes threads pode se intercalar, mas você não obtém corridas de dados).
Isso desata
cin
decout
. Os fluxos vinculados garantem que um fluxo seja liberado automaticamente antes de cada operação de E / S no outro fluxo.Por padrão,
cin
está vinculadocout
a garantir uma interação sensata do usuário. Por exemplo:Se
cin
ecout
estiver empatado, você pode esperar que a saída seja liberada (ou seja, visível no console) antes que o programa solicite a entrada do usuário. Se você desatar os fluxos, o programa poderá bloquear a espera do usuário digitar seu nome, mas a mensagem "Enter name" ainda não está visível (porquecout
é armazenada em buffer por padrão, a saída é liberada / exibida no console somente sob demanda ou quando o buffer está cheio).Então, se você desatar
cin
a partircout
, você deve certificar-se para lavarcout
manualmente cada vez que você deseja exibir algo antes de esperar a entrada emcin
.Em conclusão, saiba o que cada um deles faz, entenda as conseqüências e decida se você realmente deseja ou precisa do possível efeito colateral da melhoria da velocidade.
fonte
cout
é armazenado em buffer por um motivo, se você o descarregar com muita frequência, quando realmente não precisa, poderá ocorrer um impacto no desempenho.scanf()
, desabilitar o buffer completamente ou alternar para buffer de linha (que deve liberar após a nova linha ou quando a entrada for lidastdin
- consulte linux.die.net/man/3/setlinebuf ).Isso é para sincronizar IOs do mundo C e C ++. Se você sincronizar, terá uma garantia de que os pedidos de todas as E / S são exatamente o que você espera. Em geral, o problema é o armazenamento em buffer de E / S que causa o problema. A sincronização permite que os dois mundos compartilhem os mesmos buffers. Por exemplo
cout << "Hello"; printf("World"); cout << "Ciao";
; sem sincronização você nunca vai saber se você teráHelloCiaoWorld
ouHelloWorldCiao
ouWorldHelloCiao
...tie
permite que você garanta que os canais de pedidos de veiculação no mundo C ++ estejam ligados entre si, o que significa, por exemplo, que todas as saídas foram liberadas antes que as entradas ocorram (pense emcout << "What's your name ?"; cin >> name;
).Você sempre pode misturar IOs C ou C ++, mas se desejar um comportamento razoável, deverá sincronizar os dois mundos. Cuidado: em geral, não é recomendável combiná-los, se você programar em C, usar o C stdio e se programar em C ++, usar fluxos. Mas você pode querer misturar as bibliotecas C existentes no código C ++ e, nesse caso, é necessário sincronizar as duas.
fonte
cout <<
não podem mudar de ordem, portanto,CiaoHelloWorld
não é possível para o seu caso de exemplo. A sincronização é estritamente sobre diferentes métodos de buffer.O uso
ios_base::sync_with_stdio(false);
é suficiente para desacoplar os fluxosC
eC++
. Você pode encontrar uma discussão sobre isso em IOStreams e localizações padrão do C ++ , de Langer e Kreft. Eles observam que como isso funciona é definido pela implementação.A
cin.tie(NULL)
chamada parece estar solicitando uma dissociação entre as atividades emcin
ecout
. Não sei explicar por que usar isso com a outra otimização deve causar uma falha. Como observado, o link que você forneceu é ruim, portanto não há especulação aqui.fonte
É apenas coisas comuns para fazer cin entrada funcione mais rapidamente.
Para uma explicação rápida: a primeira linha desativa a sincronização de buffer entre o cin stream e as ferramentas stdio estilo C (como scanf ou gets) - para que o cin funcione mais rápido, mas você não pode usá-lo simultaneamente com as ferramentas stdio .
A segunda linha desativa cin do cout - por padrão, o buffer do cout libera cada vez que você lê algo do cin . E isso pode ser lento quando você lê repetidamente algo pequeno e depois escreve algo pequeno várias vezes. Portanto, a linha desativa essa sincronização (amarrando literalmente cin a nulo em vez de cout ).
fonte