cout

Lesezeit: 2 Minuten

Benutzer-Avatar
endliche Schleife

der folgende Code:

myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue() << myQueue.dequeue();

gibt “ba” auf der Konsole aus

während:

myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue();
cout << myQueue.dequeue();

gibt “ab” aus, warum ist das so?

Es scheint, als ob cout zuerst die äußerste (am nächsten an der 😉 Funktion aufruft und sich hineinarbeitet, verhält es sich so?

  • Wo sind all die Antworten geblieben? jetzt gibt es nur noch einen?

    – endliche Schleife

    24. Januar 2010 um 22:53 Uhr


  • Die Antwortenden löschten sie, weil sie erkannten, dass sie falsch lagen.

    anon

    24. Januar 2010 um 22:54 Uhr

  • Manche Leute löschen Antworten, wenn sie feststellen, dass sie falsch sind.

    – Anonym.

    24. Januar 2010 um 22:55 Uhr

Benutzer-Avatar
CB Bailey

Es gibt keinen Sequenzpunkt mit << -Operator, sodass der Compiler beides auswerten kann dequeue Funktion zuerst. Was garantiert ist, ist das Ergebnis des zweiten dequeue Aufruf (in der Reihenfolge, in der er im Ausdruck erscheint und nicht unbedingt in der Reihenfolge, in der er ausgewertet wird) ist <<‘ed zum Ergebnis von <<‘ing die erste (wenn Sie verstehen, was ich sage).

Dem Compiler steht es also frei, Ihren Code in etwas wie dieses zu übersetzen (Pseudo-Intermediate-C++). Dies soll keine vollständige Liste sein.

auto tmp2 = myQueue.dequeue();
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;

oder

auto tmp1 = myQueue.dequeue();
auto tmp2 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;

oder

auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
auto tmp2 = myQueue.dequeue();
tmp3 << tmp2;

Hier ist, was die Provisorien im ursprünglichen Ausdruck entsprechen.

cout << myQueue.dequeue() << myQueue.dequeue();
|       |               |    |               |
|       |____ tmp1 _____|    |_____ tmp2 ____|
|                       |
|________ tmp3 _________|

  • im oberen Beispiel würde also std::ostream& tmp3 = cout << tmp1; tmp3 << tmp2; wie zu sagen "cout << tmp1 << tmp2;"? Oder etwas, das ich vermisse?

    – endliche Schleife

    24. Januar 2010 um 22:57 Uhr


  • @segfault: Ja, weil das so ist << Mitarbeiter in der C++-Grammatik. a << b << c gruppiert immer als (a << b) << c.

    – CB Bailey

    24. Januar 2010 um 23:03 Uhr

  • aber würde nach dieser Logik das Sagen von cout << a << b nicht sagen (cout << a) << b und alles Notwendige tun, um zuerst a zu couten (dh myQueue.dequeue() aufrufen)?

    – endliche Schleife

    24. Januar 2010 um 23:07 Uhr

  • Die Assoziativität sagt nichts über die Reihenfolge aus, in der die Teilausdrücke ausgewertet werden. cout << a << b bedeutet immer (cout << a) << b aber der Compiler kann frei evaluieren b Zuerst, dann adann die erste << Betrieb und die zweite. Genau darauf habe ich in meiner Antwort hingewiesen.

    – CB Bailey

    24. Januar 2010 um 23:11 Uhr


  • Es tut mir leid, einen alten Beitrag zu kommentieren, aber C++11 1.9/15 (C++03 1.9/17) scheint zu implizieren, dass die Sequenzierungsbeschränkungen für überladene Operatoren anders sind. Wenn ich richtig verstehe, ist das oben genannte entweder cout.operator<<(a).operator<<(b)oder operator<<(operator<<(cout,a),b) je nachdem, ob es sich bei dem Betreiber um eine Mitglieds- oder freie Funktion handelt. Beides würde eine definierte Auswertungsreihenfolge für Teilausdrücke implizieren a und b. Ist das korrekt?

    – Jogojapan

    1. März 2013 um 4:33 Uhr


Der Aufruf aus Ihrem Beispiel:

cout << myQueue.dequeue() << myQueue.dequeue();

übersetzt in den folgenden Ausdruck mit zwei Aufrufen von operator<< Funktion:

operator<<( operator<<( cout, myQueue.dequeue() ), myQueue.dequeue() );
-------------------- 1
---------2

Die Reihenfolge der Auswertung von cout, myQueue.dequeue() ist unspezifiziert. Allerdings ist die Reihenfolge der operator<< Funktionsaufrufe sind gut spezifiziert, wie mit gekennzeichnet 1 und 2

Seit C++17 hat sich das Verhalten dieses Codes geändert; der linke Operand von << wird vor dem rechten Operanden von sequenziert <<, auch wenn es sich um einen überladenen Operator handelt. Die Ausgabe muss nun erfolgen ab.

Weitere Informationen finden Sie unter: Was sind die von C++17 eingeführten Garantien für die Bewertungsreihenfolge?.

1013610cookie-checkcout

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy