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?
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
.
Der Unterschied kann durch Folgendes veranschaulicht werden:
std::cout << std::endl;
ist äquivalent zu
std::cout << '\n' << std::flush;
So,
std::endl
, wenn Sie die Ausgabe sofort bereinigen möchten.\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)).
Möglicherweise gibt es Leistungsprobleme. std::endl
erzwingt eine Leerung des Ausgabestroms.
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 .
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.
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.
Keine große Sache, aber endl funktioniert nicht in boost :: lambda .
(cout<<_1<<endl)(3); //error
(cout<<_1<<"\n")(3); //OK , prints 3
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
.
Ich hatte schon immer die Gewohnheit, nur std :: endl zu verwenden, weil es für mich leicht zu erkennen ist.
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.
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.
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