c++ coding-style iostream c++-faq

C++: "std:: endl" vs "/ n"



coding-style iostream (12)

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 realizar la E / S de archivos porque las confirmaciones innecesarias pueden afectar el rendimiento.

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 así:

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

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


Con std::endl Este es un manipulador de E / S de solo salida .

std::endl Inserta un carácter de nueva línea en la secuencia de salida os y lo os.put(os.widen(''/n'')) 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 ,

p.ej

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

Una descarga explícita de std :: cout también es necesaria 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 fuerza 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.


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

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

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


La diferencia puede ser ilustrada por lo siguiente:

std::cout << std::endl;

es equivalente a

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

Asi que,

  • Use std::endl si desea forzar una descarga inmediata a la salida.
  • Use /n si está preocupado por el rendimiento (que probablemente no sea el caso si está utilizando el operador << ).

Yo 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).

Contrariamente a otras afirmaciones, el carácter /n se asigna a la secuencia correcta de fin de línea de la plataforma solo si el flujo va a un archivo ( std::cin y std::cout son especiales pero aún son archivos (o de tipo archivo)) .


Los diferentes caracteres de fin de línea no importan, asumiendo que el archivo está abierto en modo 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 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 todos los resultados y el programa es inestable), use std::endl .



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


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

Consulte 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 escribir salida convencional) y error estándar (para escribir salida de diagnóstico). Como se abrió inicialmente, el flujo de error estándar no está completamente protegido; la entrada estándar y las secuencias de salida estándar están completamente almacenadas en búfer si, y solo si se puede determinar que la secuencia no se refiere a un dispositivo interactivo.

7.21.3 §3

Cuando un flujo no tiene buffer, se pretende que los caracteres aparezcan desde la fuente o en el destino tan pronto como sea posible. De lo contrario, los caracteres pueden acumularse y transmitirse hacia o desde el entorno host como un bloque. Cuando un flujo está completamente almacenado en búfer, se pretende que los caracteres se transmitan hacia o desde el entorno del host como un bloque cuando se llena un búfer. Cuando un flujo tiene un búfer de línea, se pretende que los caracteres se transmitan hacia o desde el entorno del host como un bloque cuando se encuentra un carácter de nueva línea. Además, se pretende que los caracteres se transmitan como un bloque al entorno del host 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 un flujo del búfer de línea que requiere la transmisión de caracteres desde el entorno del host . El soporte para estas características está definido por la implementación y puede verse afectado a través de las funciones setbuf y setvbuf.

Esto significa que std::cout y std::cin están completamente almacenados en búfer si, y solo si , se refieren a un dispositivo no 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 menos que se std::endl a los archivos: std::endl .


Si no lo notaste, endl es como presionar la tecla ENTER mientras que "/n" es como presionar la tecla ENTER + SPACE BAR.


Si tiene la intención de ejecutar su programa en otra cosa que no sea su propia computadora portátil, nunca use la instrucció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.


Si usas Qt y endl, podrías accidentalmente usar el endl equivocado, 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, ese fue mi error, ya que debería haber escrito std::endl , pero si usas endl , qt y using 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: Olvidé mencionar, el endl de Qt se declara en "qtextstream.h" que es parte de QtCore

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


Siempre he tenido el hábito de usar std :: endl porque me resulta fácil verlo.