it-swarm.com.de

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

Viele C++ - Bücher enthalten Beispielcode wie folgt ...

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

... das habe ich auch immer gemacht. Stattdessen habe ich viel Code von arbeitenden Entwicklern gesehen:

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

Gibt es einen technischen Grund, einen zu bevorzugen, oder ist es nur eine Frage des Codierstils?

480
Head Geek

Die abweichenden Zeilenendezeichen spielen keine Rolle, vorausgesetzt die Datei ist im Textmodus geöffnet. Das kompilierte Programm schreibt das richtige für das kompilierte System aus.

Der einzige Unterschied besteht darin, dass std::endl den Ausgabepuffer leert und '\n' dies nicht tut. Wenn Sie nicht möchten, dass der Puffer häufig geleert wird, verwenden Sie '\n'. Wenn dies der Fall ist (wenn Sie beispielsweise die gesamte Ausgabe abrufen möchten und das Programm nicht stabil ist), verwenden Sie std::endl.

410
David Thornley

Der Unterschied kann durch Folgendes veranschaulicht werden:

std::cout << std::endl;

ist äquivalent zu

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

So,

  • Verwenden Sie std::endl, wenn Sie die Ausgabe sofort bereinigen möchten.
  • Verwenden Sie \n, wenn Sie sich Sorgen um die Leistung machen (was bei Verwendung des <<-Operators wahrscheinlich nicht der Fall ist).

Ich benutze \n in den meisten Zeilen.
.__ Verwenden Sie dann std::endl am Ende eines Absatzes (dies ist jedoch nur eine Gewohnheit und normalerweise nicht notwendig).

Im Gegensatz zu anderen Ansprüchen wird das \n-Zeichen nur dann der richtigen Plattform-Zeilenende-Sequenz zugeordnet, wenn der Stream in eine Datei geht (std::cin und std::cout sind spezielle Dateien, aber Dateien (oder dateiähnlich)).

205
Martin York

Möglicherweise gibt es Leistungsprobleme. std::endl erzwingt eine Leerung des Ausgabestroms.

40
Martin Beckett

Ich erinnerte mich an das Lesen im Standard, also hier:

Siehe C11-Standard, der definiert, wie sich die Standardströme verhalten. Da C++ - Programme die CRT-Schnittstelle bilden, sollte der C11-Standard die Flush-Richtlinie hier festlegen.

ISO/IEC 9899: 201x

7.21.3 §7

Beim Programmstart sind drei Textströme vordefiniert und müssen nicht explizit geöffnet werden - Standardeingabe (zum Lesen einer konventionellen Eingabe), Standardausgabe (zum Schreiben Konventioneller Ausgabe) und Standardfehler (zum Schreiben einer Diagnoseausgabe). Wie anfangs geöffnet, der Standardfehlerstrom ist nicht vollständig gepuffert; die Standardeingabe und Standard Ausgabeströme werden nur dann vollständig gepuffert, wenn bestimmt werden kann, dass der Strom nicht referenziert wird zu einem interaktiven Gerät.

7.21.3 §3

Wenn ein Stream nicht gepuffert ist, sollen Zeichen von der Quelle oder am .__ angezeigt werden. Ziel so schnell wie möglich. Andernfalls können Zeichen gesammelt werden und als Block an oder von der Host-Umgebung übertragen. Wenn ein Stream vollständig gepuffert ist, Zeichen sollen als Block an die oder von der Host-Umgebung übertragen werden, wenn ein Puffer ist gefüllt. Wenn ein Stream zeilenweise gepuffert wird, sollen Zeichen .__ sein. Wird als Block an eine oder von der Host-Umgebung übertragen, wenn ein Zeichen für eine neue Zeile .__ ist. angetroffen. Darüber hinaus sollen Zeichen als Block an den Host übertragen werden Umgebung, wenn ein Puffer gefüllt ist, wenn Eingabe für einen ungepufferten Stream angefordert wird, oder wenn die Eingabe in einem zeilengepufferten Stream angefordert wird, der die Übertragung von .__ erfordert. Zeichen aus der Host-Umgebung. Unterstützung für diese Merkmale ist implementierungsdefiniert und kann über die Funktionen setbuf und setvbuf beeinflusst werden.

Dies bedeutet, dass std::cout und std::cin vollständig gepuffert sind wenn und nur wenn sie sich auf ein nicht interaktives Gerät beziehen. Wenn also stdout an ein Terminal angeschlossen ist, gibt es keinen Unterschied im Verhalten. 

Wenn jedoch std::cout.sync_with_stdio(false) aufgerufen wird, führt '\n' auch für interaktive Geräte nicht zu einem Leeren. Andernfalls ist '\n' äquivalent zu std::endl, sofern nicht an folgende Dateien weitergeleitet wird: c ++ ref unter std :: endl .

24
Emily L.

Dort ist ein weiterer Funktionsaufruf enthalten, wenn Sie std::endl verwenden.

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

a) ruft den Operator << einmal auf. 
b) ruft den Operator << zweimal auf.

23
Nathan

Beide schreiben die entsprechenden Zeilenende-Zeichen. Zusätzlich dazu bewirkt endl, dass der Puffer festgeschrieben wird. Normalerweise möchten Sie endl nicht für Datei-I/O verwenden, da unnötige Commits die Leistung beeinträchtigen können.

18
Ferruccio

Keine große Sache, aber endl funktioniert nicht in boost :: lambda .

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

(cout<<_1<<"\n")(3); //OK , prints 3
11
Özgür

Wenn Sie Qt und Endl verwenden, könnten Sie versehentlich die falsche endl verwenden, die mir heute passiert ist und ich war wie ..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();
}

Natürlich war das mein Fehler, da ich std::endl hätte schreiben sollen, wenn Sie jedoch endl, qt und using namespace std; verwenden, hängt es von der Reihenfolge der Include-Dateien ab, ob die korrekte endl verwendet wird.*

Natürlich können Sie Qt für die Verwendung eines Namespaces erneut kompilieren. In diesem Beispiel wird ein Kompilierungsfehler angezeigt.

BEARBEITEN: Vergessen zu erwähnen, Qt's endl wird in "qtextstream.h" deklariert, das Teil von QtCore ist

* EDIT2: C++ wählt die richtige endl aus, wenn Sie eine using für std::cout oder den Namespace std haben, da std::endl in demselben Namespace wie std::cout liegt, der ADL-Mechanismus von C++ std::endl.

9
smerlin

Ich hatte schon immer die Gewohnheit, nur std :: endl zu verwenden, weil es für mich leicht zu erkennen ist.

2
Zee JollyRoger

Mit reference Dies ist ein E/A-Manipulator für output-only.

std::endl Fügt ein Newline-Zeichen in die Ausgabesequenz os ein und leert es, als würde es durch Aufruf von os.put(os.widen('\n')) gefolgt von os.flush() aufgerufen. 

Wann zu verwenden:

Dieser Manipulator kann verwendet werden, um sofort eine Zeile von output zu erzeugen. 

z.B. 

bei der Anzeige von Ausgaben eines lang andauernden Prozesses, Protokollieren von Aktivitäten mehrerer Threads oder Protokollieren von Aktivitäten eines Programms, die unerwartet abstürzen können. 

Ebenfalls

Vor dem Aufruf von std :: system ist auch ein expliziter Flush von std :: cout erforderlich, wenn der erzeugte Prozess eine Bildschirm-E/A durchführt. In den meisten anderen gängigen interaktiven E/A-Szenarien ist std :: endl redundant, wenn es mit std :: cout verwendet wird, da alle Eingaben von std :: cin, die Ausgabe in std :: cerr oder die Beendigung eines Programms einen Aufruf von std :: cout erzwingen .spülen(). Die Verwendung von std :: endl anstelle von '\ n', die von einigen Quellen unterstützt wird, kann die Ausgabeleistung erheblich beeinträchtigen. 

1
Kaleem Ullah

Wenn Sie Ihr Programm auf einem anderen Laptop als Ihrem eigenen Laptop ausführen möchten, verwenden Sie niemals die Anweisung endl. Besonders, wenn Sie viele kurze Zeilen schreiben oder weil ich oft einzelne Zeichen in einer Datei gesehen habe. Die Verwendung von endl ist bekannt, um vernetzte Dateisysteme wie NFS zu beenden.

0

Der Manipulator für endl entspricht '\'. Aber endl leert immer den Stream.

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