c++ - significado - std cout
¿Está std:: cout en búfer? (5)
Solo leyendo un artículo viejo pero interesante de "Scott Meyers"
http://aristeia.com/Papers/C++ReportColumns/novdec95.pdf
Básicamente, se trata de preferir usar ''/n''
sobre std::endl
(con lo cual estoy de acuerdo y he usado el mismo aumento durante años).
PERO la última sección indica que esto no se incluyó en su libro porque todo fue discutible debido a dos puntos:
-
std::cout
no estaba en búfer. - El estado de
ios::unitbuf
en std :: cout no se define explícitamente (por lo tanto, depende de la implementación).
Hice un vistazo rápido, pero no pude encontrar una referencia explícita de estándares para 1
era cierto. ¿Es std::cout
regulado en contra de lo que siempre he entendido?
De acuerdo con esta página - http://www.programmingincpp.com/flush-the-output-stream-buffer.html - std :: cout está en búfer. He fallado algo para imprimir porque se produjo un bloqueo del programa después de la declaración cout << ... pero antes de que se vaciara:
cout << "My error or flag message, but it''s not flushed, so I never see it";
//system crash!
cout << endl;
El estándar de C ++ define todas las entradas y salidas como "como si" todas las lecturas y escrituras ocurrieran a través de las lecturas y escrituras de flujos de C ([iostream.objects.overview]):
El encabezado declara los objetos que asocian objetos con los flujos de C estándar proporcionados por las funciones declaradas en (27.9.2) e incluye todos los encabezados necesarios para usar estos objetos.
Para el comportamiento de los flujos de C estándar adjuntos a esos objetos, debemos referirnos al estándar de C (§7.19.3):
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 almacenado en búfer; 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.
Aquí cito el estándar C99, pero estoy razonablemente seguro de que (los cambios de módulo en la numeración de secciones) son iguales en todas las versiones del estándar C.
En primer lugar, no hay ningún requisito para que std::cout
(o incluso std::cerr
) sea sin búfer. El único requisito es que std::cerr
tenga establecido std::basic_ios::unitbuf
(para que se std::basic_ios::unitbuf
al final de cada función de salida: <<
o una función de salida sin formato). Por otro lado, a menos que haya llamado a std::basic_ios::sync_with_stdio(false)
, la salida a los flujos de C ++ y la salida a los flujos de C correspondientes (es decir, std::cout
y stdout
) deben tener los mismos efectos. En teoría, esto se puede hacer de varias maneras: las funciones stdout
pueden reenviarse a las de std::cout
, std::cout
output pueden reenviarse a stdout
, o pueden compartir alguna implementación de búfer común bajo el capó. En la práctica, prácticamente todas las implementaciones tienen std::cout
forwarding to stdout
.
C especifica que stderr
no debe estar completamente almacenado en búfer, y que stdout
puede estar completamente almacenado en búfer solo si se puede determinar que no se refiere a un dispositivo interactivo (para algún significado definido por la implementación de "dispositivo interactivo"). Por lo general, stdout
tendrá búfer de línea (un concepto que no existe en iostream), y stderr
tendrá búfer, pero eso no está garantizado por el estándar C (y puede que no sea cierto hoy en día; la última vez que miré realmente era más de veinte hace años que). De todos modos, una implementación que solo reenvíe a stdout
seguirá las reglas de la implementación de C a la que se reenvía, y otra que no debe seguir algunos pasos para garantizar que la salida a std::cout
y stdout
salga en el orden correcto, y ese stdout
comporta "como si" obedeciera las reglas de C.
Si está preocupado por el rendimiento, es posible que desee realizar algunas pruebas. Intente medir el tiempo que se tarda en enviar a un std::ofstream
que se ha abierto, en comparación con el tiempo que se tarda en enviar a std::cout
(con y sin haber llamado sync_with_stdio
), con la salida redirigida. Las diferencias deben ser interesantes.
Por lo que leí en here formulario, cout suele estar almacenado en búfer, pero cuando detecta que se imprime en un entorno interactivo, como la consola, se queda sin búfer.
Entonces, si redirecciona la salida (usando ''>'' en UNIX), entonces el comportamiento del búfer se activa.
Más detalles en el post vinculado.
Sí, está amortiguado:
C ++ 11 27.4.2 [narrow.stream.objects] / 3: el objeto
cout
controla la salida a un búfer de flujo asociado con la salida estándar del objeto
El artículo hace referencia a un borrador de 1995 de lo que se convirtió en el estándar C ++ 98. No tengo idea de si eso podría haber dicho algo diferente o no.
En cuanto al punto 2, unitbuf
es inicialmente falso en todos los flujos (especificados por las condiciones basic_ios
constructor basic_ios
), excepto por cerr
y wcerr
que especifican explícitamente lo contrario. De nuevo, eso puede ser diferente en el antiguo borrador al que se hace referencia.