Domanda

Molti libri in C ++ contengono un esempio di codice come questo ...

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

... quindi l'ho sempre fatto anch'io. Invece ho visto un sacco di codice da sviluppatori di lavoro come questo:

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

C'è un motivo tecnico per preferire l'uno all'altro o è solo una questione di stile di codifica?

È stato utile?

Soluzione

I vari caratteri di fine riga non contano, supponendo che il file sia aperto in modalità testo, che è ciò che ottieni a meno che non richiedi un file binario. Il programma compilato scriverà la cosa corretta per il sistema compilato.

L'unica differenza è che std :: endl svuota il buffer di output e '\ n' no. Se non si desidera svuotare frequentemente il buffer, utilizzare '\ n' . Se lo fai (per esempio, se vuoi ottenere tutto l'output e il programma è instabile), usa std :: endl .

Altri suggerimenti

La differenza può essere illustrata da quanto segue:

std::cout << std::endl;

è equivalente a

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

  • Usa std :: endl Se vuoi forzare un flush immediato all'output.
  • Usa \ n se sei preoccupato per le prestazioni (che probabilmente non è il caso se stai usando l'operatore < < ).

Uso \ n sulla maggior parte delle righe.
Quindi usa std :: endl alla fine di un paragrafo (ma è solo un'abitudine e di solito non è necessario).

Contrariamente ad altre affermazioni, il carattere \ n è mappato alla sequenza di fine riga della piattaforma corretta solo se lo stream sta andando su un file ( std :: cin e std :: cout essendo speciali ma comunque file (o file-like)).

Potrebbero esserci problemi di prestazioni, std :: endl forza un flusso del flusso di output.

Ho ricordato di averlo letto nello standard, quindi ecco:

Vedi lo standard C11 che definisce come si comportano i flussi standard, poiché i programmi C ++ interfacciano il CRT, lo standard C11 dovrebbe governare la politica di flushing qui.

  

ISO / IEC 9899: 201x

     

7.21.3 §7

     

All'avvio del programma, tre flussi di testo sono predefiniti e non devono essere aperti in modo esplicito   - input standard (per la lettura di input convenzionale), output standard (per la scrittura   output convenzionale) e errore standard (per la scrittura dell'output diagnostico). Come inizialmente   aperto, il flusso di errori standard non è completamente bufferizzato; l'input standard e lo standard   i flussi di output sono completamente bufferizzati se e solo se il flusso può essere determinato per non fare riferimento   a un dispositivo interattivo.

     

7.21.3 §3

     

Quando uno stream è senza buffer, i personaggi devono apparire dalla sorgente o da   destinazione al più presto. Altrimenti i personaggi potrebbero essere accumulati e   trasmesso da o verso l'ambiente host come blocco. Quando uno stream è completamente bufferizzato,   i caratteri devono essere trasmessi da o verso l'ambiente host come blocco quando   un buffer è riempito. Quando uno stream ha un buffer di linea, i caratteri sono pensati per essere   trasmesso da o verso l'ambiente host come blocco quando è presente un carattere di nuova riga   incontrato. Inoltre, i caratteri devono essere trasmessi come blocco all'host   ambiente quando viene riempito un buffer, quando viene richiesto l'input su un flusso senza buffer, o   quando viene richiesto l'input su un flusso con buffer di linea che richiede la trasmissione di   personaggi dall'ambiente host. Il supporto per queste caratteristiche è   definito dall'implementazione e può essere influenzato dalle funzioni setbuf e setvbuf.

Ciò significa che std :: cout e std :: cin sono completamente bufferizzati se e solo se si riferiscono a un non- dispositivo interattivo. In altre parole, se stdout è collegato a un terminale, non vi è alcuna differenza nel comportamento.

Tuttavia, se viene chiamato std :: cout.sync_with_stdio (false) , '\ n' non causerà lo scaricamento nemmeno dei dispositivi interattivi. Altrimenti '\ n' equivale a std :: endl a meno che il piping ai file: c ++ ref su std :: endl .

C'è un'altra chiamata di funzione implicita lì se hai intenzione di usare std::endl

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

a) chiama l'operatore < < una volta.
b) chiama l'operatore < < due volte.

Entrambi scriveranno i caratteri di fine riga appropriati. Oltre a questo endl, verrà eseguito il commit del buffer. Di solito non si desidera utilizzare endl quando si esegue l'I / O dei file perché i commit non necessari possono influire sulle prestazioni.

Non è un grosso problema, ma endl non funzionerà in boost :: lambda .

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

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

Se usi Qt ed endl, potresti accidentalmente usare endl sbagliato, mi è successo oggi ed ero come ..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();
}

Ovviamente quello è stato il mio errore, dato che avrei dovuto scrivere std :: endl , ma se usi endl , qt e usando lo spazio dei nomi std; dipende dall'ordine dei file include se verrà utilizzato il endl corretto. *

Ovviamente potresti ricompilare Qt per usare uno spazio dei nomi, quindi ottieni un errore di compilazione per l'esempio sopra.

EDIT: dimenticato di menzionare, il endl di Qt è dichiarato in " qtextstream.h " che fa parte di QtCore

* EDIT2: C ++ sceglierà endl se hai un usando per std :: cout o lo spazio dei nomi std , poiché std :: endl si trova nello stesso spazio dei nomi di std :: cout , il meccanismo ADL di C ++ sceglierà std :: endl .

Ho sempre avuto l'abitudine di usare solo std :: endl perché è facile per me vedere.

Con riferimento Questo è un solo output Manipolatore I / O .

std::endl inserisce un carattere di nuova riga nella sequenza di output os e lo scarica come se chiamando os.put (os.widen ('\ n ')) seguito da os.flush () .

Quando utilizzare:

Questo manipolatore può essere utilizzato per produrre immediatamente una riga di output ,

ad esempio

  

quando si visualizza l'output di un processo a esecuzione prolungata, l'attività di registrazione di più thread o l'attività di registrazione di un programma che potrebbe arrestarsi in modo imprevisto.

anche

  

È necessario anche un flush esplicito di std :: cout prima di una chiamata a std :: system, se il processo generato esegue qualsiasi I / O dello schermo. Nella maggior parte degli altri scenari di I / O interattivi usuali, std :: endl è ridondante se utilizzato con std :: cout perché qualsiasi input da std :: cin, output in std :: cerr o terminazione del programma forza una chiamata a std :: cout .flush (). L'uso di std :: endl al posto di '\ n', incoraggiato da alcune fonti, può degradare significativamente le prestazioni di output.

Se intendi eseguire il tuo programma su qualcosa di diverso dal tuo laptop, non utilizzare mai l'istruzione endl . Soprattutto se stai scrivendo molte righe brevi o come ho visto spesso singoli caratteri in un file. L'uso di endl è noto per eliminare i file system in rete come NFS.

Il manipolatore endl è equivalente a '\' . Ma endl scarica sempre lo stream.

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

Se non lo hai notato, endl è come premere il tasto INVIO mentre " \ n " è come premere il tasto ENTER + BARRA SPAZIATRICE.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top