Não sei se isso é verdade, mas quando estava lendo as Perguntas frequentes sobre um dos sites que forneciam problemas, encontrei algo que chamou minha atenção:
Verifique seus métodos de entrada / saída. No C ++, o uso de cin e cout é muito lento. Use-os e você garantirá não conseguir resolver nenhum problema com uma quantidade razoável de entrada ou saída. Use printf e scanf.
Alguém pode esclarecer isso? Realmente está usando scanf () em programas C ++ mais rápido do que algo cin >> ? Se sim, é uma boa prática usá-lo em programas C ++? Eu pensei que era específico C, embora eu esteja apenas aprendendo C ++ ...
c++
c
performance
io
zeroDivisible
fonte
fonte
Respostas:
Aqui está um teste rápido de um caso simples: um programa para ler uma lista de números da entrada padrão e XOR todos os números.
versão iostream:
versão scanf:
Resultados
Usando um terceiro programa, eu gerei um arquivo de texto contendo 33.280.276 números aleatórios. Os tempos de execução são:
Alterar as configurações de otimização do compilador não pareceu alterar muito os resultados.
Assim: realmente existe uma diferença de velocidade.
EDIT: O usuário clyfish indica abaixo que a diferença de velocidade se deve em grande parte às funções de E / S iostream, que mantêm a sincronização com as funções de CI / O. Podemos desativar isso com uma chamada para
std::ios::sync_with_stdio(false);
:Novos resultados:
C ++ iostream vence! Acontece que essa sincronização / liberação interna é o que normalmente reduz a velocidade de E / S do iostream. Se não estivermos misturando stdio e iostream, podemos desativá-lo e o iostream é o mais rápido.
O código: https://gist.github.com/3845568
fonte
iostream
perde quando você analisa mais de um número inteiro em umascanf
chamada.http://www.quora.com/Is-cin-cout-slower-than-scanf-printf/answer/Aditya-Vishwakarma
O desempenho de
cin
/cout
pode ser lento porque eles precisam se manter sincronizados com a biblioteca C subjacente. Isso é essencial se o C IO e o C ++ IO forem usados.No entanto, se você usar apenas C ++ IO, basta usar a linha abaixo antes de qualquer operação de IO.
Para obter mais informações, consulte os documentos correspondentes do libstdc ++ .
fonte
Provavelmente o scanf é um pouco mais rápido do que usar fluxos. Embora os fluxos forneçam muita segurança de tipo e não precisem analisar seqüências de caracteres de formato no tempo de execução, ele geralmente tem a vantagem de não exigir alocações de memória excessivas (isso depende do compilador e do tempo de execução). Dito isto, a menos que o desempenho seja seu único objetivo final e você esteja no caminho crítico, deve realmente favorecer os métodos mais lentos.
Há um artigo muito delicioso, escrito aqui por Herb Sutter " Os formatadores de cordas da Manor Farm ", que aborda muitos detalhes do desempenho de formatadores de cordas
sscanf
e comolexical_cast
e que tipo de coisas os fazia correr lenta ou rapidamente. Isso é análogo, provavelmente ao tipo de coisas que afetariam o desempenho entre o estilo C IO e o estilo C ++. A principal diferença com os formatadores costumava ser o tipo de segurança e o número de alocações de memória.fonte
Passei uma noite trabalhando em um problema no UVa Online (Factovisors, um problema muito interessante, confira):
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=35&page=show_problem&problem=1080
Eu estava recebendo o TLE (limite de tempo excedido) em meus envios. Nesses sites de juízes on-line para solução de problemas, você tem um prazo de 2 a 3 segundos para lidar com potencialmente milhares de casos de teste usados para avaliar sua solução. Para problemas computacionalmente intensivos como este, cada microssegundo conta.
Eu estava usando o algoritmo sugerido (leia nos fóruns de discussão do site), mas ainda estava obtendo TLEs.
Alterei apenas "cin >> n >> m" para "scanf ("% d% d ", & n, & m)" e os poucos "couts" pequenos para "printfs", e meu TLE se transformou em "Aceito"!
Então, sim, isso pode fazer uma grande diferença, especialmente quando os prazos são curtos.
fonte
Se você se preocupa com o desempenho e a formatação de cadeias, consulte a biblioteca FastFormat de Matthew Wilson .
edit - link para publicação accu nessa biblioteca: http://accu.org/index.php/journals/1539
fonte
Existem implementações stdio ( libio ) que implementam FILE * como um streambuf C ++ e fprintf como um analisador de formato de tempo de execução. Os IOstreams não precisam de análise de formato de tempo de execução, tudo é feito em tempo de compilação. Portanto, com os back-ends compartilhados, é razoável esperar que os iostreams sejam mais rápidos no tempo de execução.
fonte
Sim, o iostream é mais lento que o cstdio.
Sim, você provavelmente não deve usar o cstdio se estiver desenvolvendo em C ++.
Dito isso, existem maneiras ainda mais rápidas de obter E / S do que o scanf, se você não se importa com formatação, digite safety, blá, blá, blá ...
Por exemplo, esta é uma rotina personalizada para obter um número de STDIN:
fonte
O problema é que
cin
há muita sobrecarga envolvida porque fornece uma camada de abstração acima dasscanf()
chamadas. Você não deve usarscanf()
maiscin
se estiver escrevendo software C ++, porque é isso que é necessáriocin
. Se você deseja desempenho, provavelmente não estaria escrevendo E / S em C ++.fonte
cin
realmente mais "abstrato" (em tempo de execução) do quescanf
? Eu acho que não ...scanf
deve interpretar a string de formato em tempo de execução, enquanto queiostream
conhece o formato em tempo de compilação.std::istream
é configurada no tempo de execução (por meio de manipuladores de E / S ou pela configuração de sinalizadores noistream
próprio objeto). UmFILE*
objeto, por outro lado, não possui esse estado; portanto, uma chamada ascanf
esse respeito é muito mais estável.As demonstrações
cin
ecout
de uso geral parece ser mais lento do quescanf
eprintf
em C ++, mas na verdade eles são mais rápidos!A questão é: no C ++, sempre que você usa
cin
ecout
, ocorre um processo de sincronização por padrão que garante que, se você usa o programascanf
ecin
o programa, ambos trabalhem em sincronia. Esse processo de sincronização leva tempo. Portanto,cin
ecout
parecer mais lento.No entanto, se o processo de sincronização estiver definido para não ocorrer,
cin
será mais rápido quescanf
.Para ignorar o processo de sincronização, inclua o seguinte snippet de código no seu programa logo no início de
main()
:Visite este site para mais informações.
fonte
Há um erro no final do arquivo, mas esse código C é muito mais rápido que a versão mais rápida do C ++.
O C ++ original levou 30 segundos e o código C levou 2 segundos.
fonte
Claro que é ridículo usar o cstdio sobre o iostream. Pelo menos quando você desenvolve software (se você já estiver usando c ++ sobre c, vá até o fim e use seus benefícios, em vez de sofrer apenas pelas desvantagens).
Mas, no juiz on-line, você não está desenvolvendo software, está criando um programa que deve ser capaz de fazer as coisas que o software Microsoft leva 60 segundos para atingir em 3 segundos !!!
Portanto, neste caso, a regra de ouro é a seguinte (é claro, se você não tiver mais problemas usando java)
fonte
Mesmo se
scanf
fosse mais rápido quecin
isso, não importaria. Na grande maioria das vezes, você estará lendo no disco rígido ou no teclado. Colocar os dados brutos em seu aplicativo leva ordens de magnitude mais tempo do que levascanf
oucin
para processá-las.fonte
iostream
é mais lento que o disco rígido. Sim, é péssimo.