2010-01-23 8 views
8

Questo programma:Perché endl viene utilizzato come sinonimo di " n" anche se incorre in penalità significative per le prestazioni?

#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; 
} 

quando cronometrato in questo modo:

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

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

richiede 15,4 secondi di tempo reale di esecuzione. Sostituire la linea di uscita con questo: cout << i << ": " << msg << endl; e si finisce con qualcosa di simile:

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

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

Come si può vedere, il tempo di correre più del doppio, e il programma va di spendere tempo minimo nel sistema operativo alla spesa quasi la metà del tempo nel sistema operativo.

Entrambe le versioni del programma hanno un'uscita identica e sono garantite dallo standard per avere un'uscita identica su ogni piattaforma.

Dato questo, perché la gente persistono nell'uso endl come sinonimo di '\n'?

Edit: Nel caso in cui non è ovvio, la questione è destinato ad essere una domanda di primo piano ed è qui per scopi didattici . So perché esiste la penalizzazione delle prestazioni.

+0

Puoi farmi sapere quale parte dello standard garantisce che l'output sarà lo stesso su tutte le piattaforme? – Glen

+2

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

risposta

21

Non ne sono sicuro. L'inserimento di std::endl nel flusso di output è equivalente all'inserimento di flush() eppure molti programmatori continuano a utilizzare anche se non vi è alcuna causa per lo svuotamento, ad esempio se eseguono immediatamente l'output di qualcos'altro.

La mia ipotesi è che deriva da una convinzione errata che è in qualche modo più portabile perché non utilizza esplicitamente un carattere di fine riga specifico. Ciò non è corretto poiché \n deve sempre essere mappato alla sequenza di nuova riga corretta del sistema per i file non binari dalla libreria del flusso.

+2

Sai, sei la prima persona che ha dato una risposta reale. :-) Chiedere domande importanti non ti porta da nessuna parte su questo sito. Devo trovare un modo migliore per affermare le domande che intendo essere istruttive. – Omnifarious

+0

Ho dato anche una risposta vera, come succede. Potresti non essere d'accordo, ovviamente. –

+0

@Neil Butterworth, Oh, va bene. Sì, Charles è la seconda persona a dare una risposta reale. :-) Anche il tuo. – Omnifarious

0

La vera domanda è: perché il compilatore ha fatto fare un tale cane alla compilazione della versione finale? Se sono garantiti per avere la stessa semantica, allora dovrebbero anche avere lo stesso runtime.

Modifica: ovviamente, non ero a conoscenza del fatto che endl ha scaricato il flusso ... è quello che si ottiene per non averlo cercato.

+2

Non è garantito che abbiano la stessa semantica. –

+0

In effetti, sicuramente non hanno la stessa semantica. – Omnifarious

+0

Beh, potrebbero fare, non sono garantiti dallo standard C++. –

4

Non tutti si preoccupano così tanto delle prestazioni. Per alcune applicazioni, garantire lo streaming è molto più importante.

Edit: Inoltre, trovo endl più facile da digitare rispetto '\n' :-)

+0

In quasi nessun caso in cui vedo 'endl' usato importa in realtà se il flusso viene svuotato proprio lì e lì. :-) – Omnifarious

+0

Le applicazioni di registrazione, le comunicazioni di rete e i database vengono subito in mente. –

+0

Le persone dovrebbero usare ':: std :: cerr' o qualche altro flusso non bufferizzato per la registrazione. Non ho mai visto una seria applicazione di rete o un database che usasse iostream per la comunicazione attraverso la rete o la scrittura nel database. – Omnifarious

4

AFAIK, endl svuota anche il flusso, che può essere la causa della penalizzazione delle prestazioni.

+0

Hai ragione. std :: endl scarica il buffer di output e "\ n" no. –

+0

So perché esiste la penalizzazione delle prestazioni. :-) La mia domanda è: perché ':: std :: endl' ancora solo" cosa è fatto "anche se ha quella penalizzazione? – Omnifarious

+1

Probabilmente perché alla maggior parte dei programmatori piace quando il loro utente può vedere l'output anziché forzarlo ad aspettare fino a quando il buffer si riempie. Data la velocità dei dispositivi di output reali, non ha mai veramente importanza. –

2

Tendo ad usare endl con on stringstreams perché rende più semplice individuare interruzioni di riga mancanti.

2

La mia ipotesi è che i testi didattici utilizzino lo std::endl con la convinzione che sia più semplice e meno confuso per i principianti, e in seguito le persone si sono abituate a usarlo.

Problemi correlati