Ob absichtlich oder versehentlich, Sie haben <<am Ende der ersten Ausgabezeile, wo Sie wahrscheinlich gemeint haben ;. Sie haben also im Wesentlichen
cout << "2+3 = "; // this, of course, prints "2+3 = "
cout << cout; // this prints "1"
cout << 2 + 3; // this prints "5"
cout << endl; // this finishes the line
Die Frage läuft also darauf hinaus: Warum cout << cout;drucken "1"?
Dies stellt sich vielleicht überraschend subtil heraus. std::coutstellt über seine Basisklasse einen bestimmten Typkonvertierungsoperatorstd::basic_ios bereit , der im booleschen Kontext wie in verwendet werden soll
while (cout) { PrintSomething(cout); }
Dies ist ein ziemlich schlechtes Beispiel, da es schwierig ist, eine Ausgabe zum Scheitern zu bringen - aber std::basic_iostatsächlich eine Basisklasse für Eingabe- und Ausgabestreams ist und für die Eingabe viel sinnvoller ist:
int value;
while (cin >> value) { DoSomethingWith(value); }
(verlässt die Schleife am Ende des Streams oder wenn Stream-Zeichen keine gültige Ganzzahl bilden).
Die genaue Definition dieses Konvertierungsoperators hat sich zwischen den Versionen C ++ 03 und C ++ 11 des Standards geändert. In älteren Versionen wurde es operator void*() const;(normalerweise als return fail() ? NULL : this;) implementiert , während es in neueren Versionen explicit operator bool() const;(normalerweise einfach als return !fail();) implementiert wurde . Beide Deklarationen funktionieren in einem booleschen Kontext einwandfrei, verhalten sich jedoch unterschiedlich, wenn sie außerhalb eines solchen Kontexts (falsch) verwendet werden.
Insbesondere würde nach C ++ 03-Regeln eine Adresse cout << coutinterpretiert cout << cout.operator void*()und gedruckt. Nach C ++ 11-Regeln cout << coutsollte überhaupt nicht kompiliert werden, da der Operator deklariert ist explicitund daher nicht an impliziten Konvertierungen teilnehmen kann. Dies war in der Tat die Hauptmotivation für die Änderung - das Kompilieren von unsinnigem Code zu verhindern. Ein Compiler, der einem der beiden Standards entspricht, würde kein Programm erzeugen, das gedruckt wird "1".
Anscheinend erlauben bestimmte C ++ - Implementierungen das Mischen und Anpassen des Compilers und der Bibliothek auf eine Weise, die zu einem nicht konformen Ergebnis führt (unter Angabe von @StephanLechner: "Ich habe in xcode eine Einstellung gefunden, die 1 ergibt, und eine andere Einstellung, die eine Adresse ergibt: Sprachdialekt c ++ 98 in Kombination mit "Standardbibliothek libc ++ (LLVM-Standardbibliothek mit C ++ 11-Unterstützung)" ergibt 1, während c ++ 98 in Kombination mit libstdc (gnu c ++ Standardbibliothek) eine Adresse ergibt; "). Sie können einen C ++ 03-Compiler, der explicitKonvertierungsoperatoren (die in C ++ 11 neu sind) nicht versteht, mit einer C ++ 11-Bibliothek kombinieren, die die Konvertierung als definiert operator bool(). Mit einer solchen Mischung wird es möglich cout << cout, als interpretiert zu werden cout << cout.operator bool(), was wiederum einfach ist cout << trueund druckt "1".
;am Ende der ersten Ausgabezeile, nicht<<. Sie drucken nicht das, was Sie zu drucken glauben. Sie tuncout << cout, was druckt1(es verwendetcout.operator bool(), denke ich). Dann folgt5(von2+3) sofort und lässt es wie die Nummer fünfzehn aussehen.