C ++: “std :: endl” vs “\ n”
-
03-07-2019 - |
Pergunta
Muitos C ++ livros contêm exemplo de código como este ...
std::cout << "Test line" << std::endl;
... então eu sempre fiz isso também. Mas eu já vi um monte de código de desenvolvedores trabalhando como este em vez disso:
std::cout << "Test line\n";
Existe uma razão técnica preferir um sobre o outro, ou é apenas uma questão de estilo de codificação?
Solução
Os caracteres de delimitação de linhas diferentes, não importa, assumindo que o arquivo é aberto no modo de texto, que é o que obtém a menos que você pedir binário. O programa compilado irá escrever a coisa correta para o sistema compilado.
A única diferença é que std::endl
rubores o tampão de saída, e '\n'
não. Se você não quer que o tampão corado com freqüência, uso '\n'
. Se você fizer (por exemplo, se você deseja obter toda a saída, eo programa é instável), o uso std::endl
.
Outras dicas
A diferença pode ser ilustrada pela seguinte:
std::cout << std::endl;
é equivalente a
std::cout << '\n' << std::flush;
Assim,
- Use
std::endl
Se você quiser forçar uma lave imediatamente para a saída. - Use
\n
se você está preocupado com o desempenho (que provavelmente não é o caso se você estiver usando o operador<<
).
Eu uso \n
na maioria das linhas.
Em seguida, use std::endl
no final de um parágrafo (mas isso é apenas um hábito e não costumam ser necessário).
Ao contrário de outras reivindicações, o personagem \n
é mapeado para o fim plataforma correta da seqüência de linha somente se o fluxo está indo para um arquivo (arquivos std::cin
e std::cout
ser especial, mas ainda (ou arquivo-like)).
Pode haver problemas de desempenho, forças std::endl
uma onda de fluxo de saída.
Lembrei-me de ler sobre isso no padrão, então aqui vai:
Veja C11 padrão que define como os fluxos padrão se comportam, como programas em C ++ de interface do CRT, o padrão C11 devem reger a política rubor aqui.
ISO / IEC 9899: 201x
7.21.3 §7
No início do programa, três fluxos de texto são predefinidos e não precisa ser aberto explicitamente - entrada padrão (para leitura de entrada convencional), a saída padrão (para a escrita saída convencional), e erro padrão (para escrever saída de diagnóstico). como inicialmente aberta, o fluxo de erro padrão não é totalmente tamponada; a entrada padrão e padrão fluxos de saída estão completamente armazenados se e não só, se a corrente pode ser determinada para se referir para um dispositivo interactivo.
7.21.3 §3
Quando um fluxo é sem buffer, os personagens são destinados a aparecer a partir da fonte ou no destino o mais rápido possível. Caso contrário, os caracteres podem ser acumulados e transmitidos para ou a partir do meio de acolhimento como um bloco. Quando uma corrente está totalmente tamponada, caracteres se destinam a ser transmitidos para ou a partir do meio de acolhimento como um bloco quando um tampão está cheia. Quando uma corrente é tamponada linha, os caracteres se destinam a ser transmitidos para ou a partir do ambiente de host como um bloco quando um caractere de nova linha é encontrado. Além disso, os caracteres se destinam a ser transmitidos como um bloco para o hospedeiro ambiente quando um tampão está cheia, quando a entrada for solicitada a corrente não tamponada, ou quando a entrada é solicitada em uma linha de fluxo tamponada que requer a transmissão de personagens do ambiente de host. O apoio a estas características é , E pode ser afectada por meio das funções setbuf e setvbuf definido pela implementação.
Isto significa que std::cout
e std::cin
estão totalmente em buffer se e só se eles estão se referindo a um dispositivo não-interativo. Em outras palavras, se stdout está ligado a um terminal, em seguida, não há nenhuma diferença no comportamento.
No entanto, se std::cout.sync_with_stdio(false)
é chamado, então '\n'
não irá causar um flush até mesmo para dispositivos interativos. Caso contrário '\n'
é equivalente a std::endl
menos tubulação de arquivos:. c ++ ref em std :: endl
Há uma outra chamada de função implícita lá se você estiver indo para usar std::endl
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
a) chama operador <<
uma vez.
b) chama <<
operador duas vezes.
Eles serão ambas escreve o caractere apropriado de fim de linha (s). Além de que endl fará com que o tampão deve ser comprometida. Você normalmente não quiser usar endl ao fazer arquivo de I / O, porque os commits desnecessários pode afetar o desempenho.
Não é grande coisa, mas endl não vai funcionar em boost :: lambda .
(cout<<_1<<endl)(3); //error
(cout<<_1<<"\n")(3); //OK , prints 3
Se você usar o Qt e endl, você pode acidentalmente usar o endl
errado, aconteceu comigo hoje e eu era como ..WTF ??
#include <iostream>
#include <QtCore/QtCore>
#include <QtGui/QtGui>
//notice that i dont have a "using namespace std;"
int main(int argc, char** argv)
{
QApplication qapp(argc,argv);
QMainWindow mw;
mw.show();
std::cout << "Finished Execution !" << endl << "...";
// Line above printed: "Finished Execution !67006AB4..."
return qapp.exec();
}
É claro que foi o meu erro, desde que eu deveria ter escrito std::endl
, , mas se você usar * endl
, qt e using namespace std;
depende da ordem dos arquivos incluem se o endl
correto será usado.
Claro que você pode recompilar Qt para usar um namespace, de modo a obter um erro de compilação para o exemplo acima.
EDIT: Esqueci de mencionar, endl
do Qt é declarada em "qtextstream.h" que faz parte do QtCore
* EDIT2:. C ++ irá escolher o endl
correta se você tiver um using
para std::cout
ou o std
namespace, uma vez std::endl
é no mesmo namespace como std::cout
, mecanismo ADL C ++ 's vai pegar std::endl
Eu sempre tive o hábito de apenas usando std :: endl, porque é fácil para mim ver.
Com referência Este é um output-only I / O manipulador .
std::endl
Insere um caractere de nova linha para o OS sequência de saída e libera-lo como se chamando os.put(os.widen('\n'))
seguido por os.flush()
.
Quando usar:
Este manipulador pode ser usado para produzir uma linha de saída imediatamente ,
por exemplo.
ao exibir a saída de um processo de longa duração, registrando a atividade de vários segmentos ou entrar actividade de um programa que pode falhar de forma inesperada.
Também
Um esvaziamento explícito de std :: cout também é necessária antes de uma chamada para std :: sistema, se executa o processo gerado qualquer tela I / O. Na maioria dos outros cenários habituais I / O interativos, std :: endl é redundante quando usado com std :: cout porque qualquer entrada de std :: cin, saída para std :: cerr, ou forças de terminação programa uma chamada para std :: cout .rubor(). Uso de std :: endl no lugar de '\ n', encorajados por algumas fontes, pode desempenho de saída significativamente degrade.
Se você pretende executar o programa em qualquer outra coisa do que o seu próprio computador portátil, nunca use a instrução endl
. Especialmente se você estiver escrevendo um monte de linhas curtas ou como muitas vezes tenho visto caracteres simples para um arquivo. O uso de endl
é saber para matar os sistemas de arquivos em rede como NFS.
O manipulador endl
é equivalente a '\'
. Mas endl
sempre libera o fluxo.
std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
Se você não percebeu, endl
é como pressionar a tecla Enter enquanto "\n"
é como pressionar ENTER CHAVE + barra de espaço.