C ++: „std :: endl“ vs „\ n“
-
03-07-2019 - |
Frage
Viele C ++ Bücher enthalten Beispielcode wie folgt ...
std::cout << "Test line" << std::endl;
... also habe ich immer das auch getan. Aber ich habe wie diese anstelle von arbeiten die Entwickler eine Menge Code zu sehen:
std::cout << "Test line\n";
Gibt es einen technischen Grund, einen über den anderen zu bevorzugen, oder ist es nur eine Frage Art der Codierung?
Lösung
Die unterschiedlichen Zeilenende-Zeichen keine Rolle spielt, ist die Datei unter der Annahme, im Textmodus geöffnet, das ist, was Sie bekommen, wenn Sie für binäre fragen. Das kompilierte Programm wird die richtige Sache für das System für kompiliert schreiben.
Der einzige Unterschied besteht darin, dass std::endl
die Ausgangspuffer Wallungen, und '\n'
nicht. Wenn Sie häufig gespült nicht den Puffer möchten, verwenden Sie '\n'
. Wenn Sie (zum Beispiel, wenn Sie alle die Ausgabe erhalten möchten, und das Programm ist instabil) Verwenden Sie dazu std::endl
.
Andere Tipps
Der Unterschied kann durch die folgenden dargestellt werden:
std::cout << std::endl;
entspricht
std::cout << '\n' << std::flush;
So
- Verwenden Sie
std::endl
Wenn Sie eine sofortige Spülung mit dem Ausgang erzwingen wollen. - Verwenden Sie
\n
, wenn Sie über die Leistung besorgt sind (was wahrscheinlich nicht der Fall ist, wenn Sie die<<
Operator verwenden).
Ich benutze \n
auf den meisten Strecken.
Dann std::endl
am Ende eines Absatzes verwenden (aber das ist nur eine Gewohnheit und in der Regel nicht erforderlich).
Im Gegensatz zu anderen Ansprüchen wird der \n
Charakter auf die richtige Plattform Zeilenende-Sequenz abgebildet nur dann, wenn der Strom in eine Datei wird (std::cin
und std::cout
seine besondere, aber immer noch Dateien (oder Datei-like)).
Es können Leistungsprobleme sein, std::endl
erzwingt einen Flush des Ausgangsstroms.
erinnerte ich mich im Standard über die Lektüre dieses, so hier geht:
Siehe C11-Standard, der definiert, wie der Standard-Streams verhalten, wie C ++ Programme, um die CRT-Schnittstelle, der C11-Standard hier die Spülung Politik bestimmen sollte.
ISO / IEC 9899: 201x
7.21.3 §7
Bei Programmstart sind drei Textströme vorgegeben und müssen nicht explizit geöffnet werden - Standardeingabe (zum Lesen von herkömmlicher Eingabe), Standardausgabe (zum Schreiben herkömmlicher Ausgang), und der Standardfehler (zum Schreiben Diagnoseausgang). wie eingangs geöffnet wird, wird der Standardfehlerstrom nicht vollständig gepuffert; die Standardeingabe und Standard Ausgangsströme werden gepuffert vollständig, wenn und nur dann, wenn der Strom nicht beziehen bestimmt werden kann zu einem interaktiven Gerät.
7.21.3 §3
Wenn ein Strom ungepufferte ist, sind Zeichen bestimmt von der Quelle erscheinen oder bei der Ziel so schnell wie möglich. Andernfalls kann es sein Zeichen gesammelt und zu oder von der Host-Umgebung als ein Block übertragen wird. Wenn ein Strom vollständig gepuffert, Zeichen werden soll oder von der Host-Umgebung als ein Block zu übertragen ist, wenn ein Puffer gefüllt ist. Wenn eine Stromlinie gepuffert wird, werden Zeichen sein soll zu oder von der Host-Umgebung als ein Block übertragen werden, wenn ein neue Zeilen Charakter angetroffen. Außerdem werden Zeichen bestimmt als Block an den Host übertragen werden Umgebung, wenn ein Puffer gefüllt ist, wenn der Eingang auf einem ungepufferten Strom angefordert wird, oder wenn der Eingang auf einer Leitung gepufferten Strom angefordert wird, die erfordert, um die Übertragung von Zeichen aus der Host-Umgebung. Die Unterstützung für diese Eigenschaften ist Implementierung definiert und kann über die setbuf und setvbuf Funktionen beeinträchtigt werden.
Das bedeutet, dass std::cout
und std::cin
vollständig gepuffert , wenn und nur wenn sie auf ein nicht-interaktives Gerät bezieht, wird. Mit anderen Worten, wenn stdout an ein Endgerät angeschlossen ist, dann gibt es keinen Unterschied im Verhalten.
Wenn jedoch std::cout.sync_with_stdio(false)
genannt wird, dann wird '\n'
nicht einen Flush sogar zu interaktiven Geräten verursachen. Ansonsten ist '\n'
gleichwertig, wenn nicht Rohrleitungen, um Dateien zu std::endl
. c ++ ref auf std :: endl
Es gibt einen anderen Funktionsaufruf dort implizierte, wenn du gehst std::endl
verwenden
a) std::cout << "Hello\n";
b) std::cout << "Hello" << std::endl;
a) ruft Operator <<
einmal.
b) ruft Operator <<
zweimal.
Sie werden beide schreiben die entsprechenden End-of-line-Zeichen (s). Zusätzlich zu diesem Endl bewirkt, dass der Puffer begangen werden. Sie in der Regel nicht wollen, Endl verwenden, wenn Datei, die ich tun / O, da die unnötigen Commits Leistung auswirken kann.
Keine große Sache, aber endl wird nicht funktionieren 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, mir passiert heute, 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 ist das mein Fehler war, da ich std::endl
geschrieben haben sollte, , aber wenn Sie verwenden * endl
, qt und using namespace std;
es auf die Reihenfolge der Include-Dateien abhängig, ob der richtige endl
verwendet wird.
Natürlich könnte man Qt neu kompiliert einen Namespace zu verwenden, so dass Sie über einen Kompilierungsfehler für das Beispiel erhalten.
EDIT: vergessen zu erwähnen, Qt endl
wird in "qtextstream.h" erklärt, die Teil QtCore
* EDIT 2:. C ++ wird den richtigen endl
wählen, wenn Sie einen using
für std::cout
oder den Namespace std
haben, da std::endl
im gleichen Namensraum wie std::cout
ist, C ++ 's ADL Mechanismus std::endl
wählen
Ich habe schon immer eine Gewohnheit, nur mit std :: endl, weil es einfach für mich, zu sehen ist.
Mit Referenz Dies ist ein output-only I / O-Manipulator .
std::endl
Fügt ein Newline-Zeichen in die Ausgangssequenz os und spült es, als ob durch os.put(os.widen('\n'))
von os.flush()
gefolgt aufrufen.
Wenn verwenden:
Dieser Manipulator kann eine Reihe von Ausgang sofort
zu erzeugen, verwendet werden,z.
, wenn der Ausgang von einem langlaufende Prozess anzeigt, Logging Aktivität mehrerer Threads oder Protokollaktivität eines Programms, das unerwartet abstürzen.
Auch
Eine explizite Flush von std :: cout ist auch notwendig, bevor ein Aufruf an std :: System, wenn der erzeugte Prozess auf einen beliebigen Bildschirm führt I / O. In den meisten anderen üblichen interaktiven E / A-Szenarien, std :: endl ist überflüssig, wenn sie mit std :: cout verwendet, da jeder Eingang von std :: cin, Ausgabe auf std :: cerr oder zum Programmende erzwingt einen Aufruf an std :: cout .spülen(). Die Verwendung von std :: endl anstelle von ‚\ n‘, die von einigen Quellen gefördert werden, kann erheblich Ausgangsleistung verschlechtern.
Wenn Sie Ihr Programm auf etwas anderes als seinen eigenen Laptop laufen, benutzen Sie nie die endl
Aussage. Vor allem, wenn Sie eine Menge von kurzen Zeilen schreiben, oder wie ich es oft einzelne Zeichen in eine Datei gesehen habe. Die Verwendung von endl
wird wissen vernetzten Dateisysteme wie NFS zu töten.
Der endl
Manipulator entspricht '\'
. Aber endl
spült immer den Strom.
std::cout << "Test line" << std::endl; // with flush
std::cout << "Test line\n"; // no flush
Wenn Sie nicht bemerkt, endl
ist wie die ENTER-Taste drücken, während "\n"
ist wie ENTER KEY + Leertaste drücken.