Pregunta

Muchos libros de C ++ contienen código de ejemplo como este ...

std::cout << "Test line" << std::endl;

... así que siempre he hecho eso también. Pero he visto un montón de código de desarrolladores que trabajan como este en su lugar:

std::cout << "Test line\n";

¿Hay una razón técnica para preferir una sobre la otra, o es solo una cuestión de estilo de codificación?

¿Fue útil?

Solución

Los caracteres de final de línea variables no importan, asumiendo que el archivo está abierto en modo de texto, que es lo que obtienes a menos que solicites un binario. El programa compilado escribirá lo correcto para el sistema compilado para.

La única diferencia es que std :: endl vacía el búfer de salida, y '\ n' no lo hace. Si no desea que el búfer se vacíe con frecuencia, use '\ n' . Si lo hace (por ejemplo, si desea obtener toda la salida y el programa es inestable), use std :: endl .

Otros consejos

La diferencia se puede ilustrar con lo siguiente:

std::cout << std::endl;

es equivalente a

std::cout << '\n' << std::flush;

Entonces,

  • Use std :: endl si desea forzar un vaciado inmediato a la salida.
  • Utilice \ n si está preocupado por el rendimiento (que probablemente no sea el caso si está utilizando el operador < < ).

Uso \ n en la mayoría de las líneas.
Luego use std :: endl al final de un párrafo (pero eso es solo un hábito y no suele ser necesario).

Al contrario de otras afirmaciones, el carácter \ n se asigna a la secuencia correcta de fin de línea de la plataforma solo si la secuencia va a un archivo ( std :: cin y std :: cout son especiales pero archivos fijos (o como archivos)).

Puede haber problemas de rendimiento, std :: endl obliga a una descarga de la secuencia de salida.

Recordé haber leído sobre esto en el estándar, así que aquí va:

Vea el estándar C11 que define cómo se comportan los flujos estándar, ya que los programas C ++ se interconectan con el CRT, el estándar C11 debe regir la política de descarga aquí.

  

ISO / IEC 9899: 201x

     

7.21.3 §7

     

Al inicio del programa, tres flujos de texto están predefinidos y no es necesario abrirlos explícitamente   - Entrada estándar (para leer entrada convencional), salida estándar (para escritura   salida convencional), y error estándar (para escribir salida de diagnóstico). Como inicialmente   abierto, el flujo de error estándar no está completamente en búfer; La entrada estándar y estándar.   los flujos de salida están completamente almacenados en búfer si y solo si se puede determinar que el flujo no haga referencia   a un dispositivo interactivo.

     

7.21.3 §3

     

Cuando una secuencia no tiene buffer, se pretende que los caracteres aparezcan desde la fuente o en la   Destino lo antes posible. De lo contrario los caracteres pueden ser acumulados y   transmitido hacia o desde el entorno host como un bloque. Cuando una secuencia está completamente amortiguada,   los caracteres deben transmitirse hacia o desde el entorno host como un bloque cuando   se llena un búfer. Cuando una secuencia tiene búfer de línea, los caracteres están destinados a ser   transmitido hacia o desde el entorno del host como un bloque cuando un carácter de nueva línea es   encontrado. Además, los caracteres están destinados a ser transmitidos como un bloque al host   ambiente cuando se llena un búfer, cuando se solicita la entrada en un flujo no almacenado en búfer, o   cuando se solicita la entrada en una línea de transmisión en búfer que requiere la transmisión de   personajes del entorno host. El soporte para estas características es   definida por la implementación, y puede verse afectada a través de las funciones setbuf y setvbuf.

Esto significa que std :: cout y std :: cin están completamente almacenados en si y solo si se están refiriendo a un no dispositivo interactivo En otras palabras, si stdout se adjunta a un terminal, entonces no hay diferencia en el comportamiento.

Sin embargo, si se llama a std :: cout.sync_with_stdio (false) , '\ n' no causará una descarga ni siquiera a dispositivos interactivos. De lo contrario, '\ n' es equivalente a std :: endl a menos que se canalice a los archivos: c ++ ref on std :: endl .

Hay otra función llamada implícita allí si vas a usar std::endl

a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;

a) llama al operador < < una vez.
b) llama al operador < < dos veces.

Ambos escribirán los caracteres de final de línea apropiados. Además de eso, endl hará que el búfer se confirme. Por lo general, no desea usar endl al hacer E / S de archivo porque las confirmaciones innecesarias pueden afectar el rendimiento.

No es un gran problema, pero endl no funcionará en boost :: lambda .

(cout<<_1<<endl)(3); //error

(cout<<_1<<"\n")(3); //OK , prints 3

Si usas Qt y endl, accidentalmente podrías usar el endl incorrecto, me pasó hoy y 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();
}

Por supuesto que fue mi error, ya que debería haber escrito std :: endl , pero si usa endl , qt y usando namespace std; depende del orden de los archivos de inclusión si se utilizará el endl correcto. *

Por supuesto, puede volver a compilar Qt para usar un espacio de nombres, por lo que obtiene un error de compilación para el ejemplo anterior.

EDITAR: Se olvidó de mencionar, el endl de Qt se declara en " qtextstream.h " que es parte de QtCore

* EDIT2: C ++ seleccionará el endl correcto si tiene un usando para std :: cout o el espacio de nombres std , dado que std :: endl está en el mismo espacio de nombres que std :: cout , el mecanismo ADL de C ++ seleccionará std :: endl .

Siempre he tenido la costumbre de usar std :: endl porque me resulta fácil verlo.

Con referencia Esto es solo una salida Manipulador de E / S .

std::endl Inserta un carácter de nueva línea en la secuencia de salida os y lo vacía como si llamara a os.put (os.widen ('\ n ')) seguido de os.flush () .

Cuándo usar:

Este manipulador se puede usar para producir una línea de salida inmediatamente ,

por ejemplo

  

cuando se muestra el resultado de un proceso de larga duración, la actividad de registro de varios subprocesos o la actividad de registro de un programa que puede fallar inesperadamente.

También

  

También es necesaria una descarga explícita de std :: cout antes de una llamada a std :: system, si el proceso generado realiza cualquier E / S de pantalla. En la mayoría de los otros escenarios de E / S interactivos habituales, std :: endl es redundante cuando se usa con std :: cout porque cualquier entrada de std :: cin, salida a std :: cerr, o terminación de programa obliga a una llamada a std :: cout .rubor(). El uso de std :: endl en lugar de '\ n', alentado por algunas fuentes, puede degradar significativamente el rendimiento de salida.

Si tiene la intención de ejecutar su programa en otra cosa que no sea su propia computadora portátil, nunca use la declaración endl . Especialmente si está escribiendo muchas líneas cortas o porque a menudo he visto caracteres individuales en un archivo. El uso de endl es conocido para eliminar sistemas de archivos en red como NFS.

El manipulador endl es equivalente a '\' . Pero endl siempre descarga la secuencia.

std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush

Si no se dio cuenta, endl es como presionar la TECLA ENTER mientras que " \ n " es como presionar ENTER KEY + BARRA ESPACIADORA.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top