2010-01-23 16 views
8

Este programa:¿Por qué endl se usa como sinónimo de " n" aunque incurre en penalizaciones de rendimiento significativas?

#include <iostream> 
#include <cstdlib> 
#include <string> 

int main(int argc, const char *argv[]) 
{ 
    using ::std::cerr; 
    using ::std::cout; 
    using ::std::endl; 

    if (argc < 2 || argc > 3) { 
     cerr << "Usage: " << argv[0] << " [<count>] <message>\n"; 
     return 1; 
    } 
    unsigned long count = 10000; 
    if (argc > 2) { 
     char *endptr = 0; 
     count = ::std::strtoul(argv[1], &endptr, 10); 
     if ((argv[1][0] == '\0') || (*endptr != '\0')) { 
     cerr << "Usage: " << argv[0] << " [<count>] <message>\n"; 
     return 1; 
     } 
    } 
    const ::std::string msg((argc < 3) ? argv[1] : argv[2]); 
    for (unsigned long i = 0; i < count; ++i) { 
     cout << i << ": " << msg << '\n'; 
    } 
    return 0; 
} 

cuando programado de esta manera:

$ time ./joe 10000000 fred >/dev/null 

real 0m15.410s 
user 0m10.551s 
sys 0m0.166s 

toma 15,4 segundos de tiempo real para ejecutar. Vuelva a colocar la línea de salida con esto: cout << i << ": " << msg << endl; y terminas con algo como esto:

$ time ./joe 10000000 fred >/dev/null 

real 0m39.115s 
user 0m16.482s 
sys 0m15.803s 

Como se puede ver, el tiempo para correr a más del doble, y el programa pasa de pasar el tiempo mínimo en el sistema operativo para el gasto casi la mitad de su tiempo en el sistema operativo.

Ambas versiones del programa tienen salida idéntica, y están garantizadas por el estándar para tener salida idéntica en cada plataforma.

Teniendo en cuenta esto, ¿por qué la gente insiste en el uso de endl como sinónimo de '\n'?

Editar: En caso de que no es obvio, esta cuestión está destinada a ser una cuestión de liderazgo y está aquí para fines de instrucción . Sé por qué existe la penalización de rendimiento.

+0

¿Puede decirme qué parte de la norma garantiza que la salida será la misma en todas las plataformas? – Glen

+2

Ver: http://stackoverflow.com/questions/213907/c-stdendl-vs-n –

Respuesta

21

No estoy seguro. Insertar std::endl en el flujo de salida se define como equivalente a insertar .widen('\n') y luego llamar al flush() y, sin embargo, muchos programadores persisten en usar std::endl incluso cuando no hay motivo para enjuagar, por ejemplo, continúan produciendo inmediatamente otra cosa.

Mi suposición es que proviene de una creencia incorrecta de que de alguna manera es más portátil porque no usa explícitamente un carácter de nueva línea específico. Esto es incorrecto ya que \n siempre se debe asignar a la secuencia de nueva línea correcta del sistema para archivos no binarios por la biblioteca de transmisión.

+2

Ya sabes, eres la primera persona que dio una respuesta real. :-) Hacer preguntas importantes no te lleva a ninguna parte en este sitio. Necesito encontrar una mejor manera de plantear las preguntas que pretendo ser instructivo. – Omnifarious

+0

Di una respuesta real también, como sucede. Puede que no estés de acuerdo, por supuesto. –

+0

@Neil Butterworth, Oh, está bien. Sí, Charles es la segunda persona en dar una respuesta real. :-) La tuya también. – Omnifarious

0

La verdadera pregunta es, ¿por qué el compilador hizo un desayuno de perros para compilar la versión endl? Si se garantiza que tienen la misma semántica, entonces también deberían tener el mismo tiempo de ejecución.

Edit: obviamente, no sabía que endl enrojeció la transmisión ... eso es lo que obtienes por no buscarlo.

+2

No se garantiza que tengan la misma semántica. –

+0

Ellos, de hecho, definitivamente no tienen la misma semántica. – Omnifarious

+0

Bueno, podrían hacerlo, simplemente no están garantizados por el estándar C++. –

4

No a todo el mundo le importa mucho el rendimiento. Para algunas aplicaciones, garantizar el flujo de la corriente es mucho más importante.

Editar: Además, me parece endl más fácil de escribir que '\n' :-)

+0

En casi ningún caso donde veo 'endl' usado realmente importa si la corriente se vacía en ese mismo momento. :-) – Omnifarious

+0

Las aplicaciones de registro, las comunicaciones de red y las bases de datos vienen inmediatamente a la mente. –

+0

Las personas deberían usar ':: std :: cerr' u otro flujo no almacenado para el registro. Nunca he visto una aplicación de red seria o una base de datos que utiliza iostreams para la comunicación a través de la red o escribir en la base de datos. – Omnifarious

4

Que yo sepa, endl también vuelca la corriente, que puede ser la causa de la pérdida de rendimiento.

+0

Tienes razón. std :: endl vacía el buffer de salida, y "\ n" no. –

+0

Sé por qué existe la penalización de rendimiento. :-) Mi pregunta es: ¿Por qué ':: std :: endl' sigue siendo solo" lo que está hecho "a pesar de que tiene esa penalización de rendimiento? – Omnifarious

+1

Probablemente porque a la mayoría de los programadores les gusta cuando su usuario puede ver el resultado en lugar de forzarlos a esperar hasta que el búfer se llene. Dada la velocidad de los dispositivos de salida reales, nunca importa realmente. –

2

Tiendo a usar endl con cadenas de caracteres, ya que es fácil detectar saltos de línea faltantes.

2

Supongo que los textos de instrucción usan std::endl con la creencia de que es más simple y menos confuso para los principiantes, y después las personas se acostumbraron a usarlo.

Cuestiones relacionadas