Technisch gesehen ist dies insgesamt undefiniertes Verhalten .
Die Antwort hat jedoch zwei wichtige Aspekte.
Die Code-Anweisung:
std::cout << a++ << a;
wird bewertet als:
std::operator<<(std::operator<<(std::cout, a++), a);
Der Standard definiert nicht die Reihenfolge der Bewertung von Argumenten für eine Funktion.
Also entweder:
std::operator<<(std::cout, a++) wird zuerst ausgewertet oder
awird zuerst ausgewertet oder
- Es kann sich um eine beliebig implementierungsdefinierte Reihenfolge handeln.
Diese Bestellung ist gemäß Standard nicht spezifiziert [Ref. 1] .
[Ref 1] C ++ 03 5.2.2 Funktionsaufruf
Abs. 8
Die Reihenfolge der Bewertung der Argumente ist nicht angegeben . Alle Nebenwirkungen von Argumentausdrucksauswertungen werden wirksam, bevor die Funktion eingegeben wird. Die Reihenfolge der Auswertung des Postfix-Ausdrucks und der Liste der Argumentausdrücke ist nicht angegeben.
Ferner gibt es keinen Sequenzpunkt zwischen der Auswertung von Argumenten für eine Funktion, aber ein Sequenzpunkt existiert erst nach Auswertung aller Argumente [Ref. 2] .
[Ref 2] C ++ 03 1.9 Programmausführung [intro.execution]:
Abs. 17:
Beim Aufrufen einer Funktion (unabhängig davon, ob die Funktion inline ist oder nicht) gibt es nach der Auswertung aller Funktionsargumente (falls vorhanden) einen Sequenzpunkt, der vor der Ausführung von Ausdrücken oder Anweisungen im Funktionskörper erfolgt.
Beachten Sie, dass hier cmehrmals auf den Wert von zugegriffen wird, ohne dass ein dazwischenliegender Sequenzpunkt vorhanden ist. Diesbezüglich lautet der Standard:
[Ref 3] C ++ 03 5 Ausdrücke [Ausdruck]:
Abs. 4:
....
Zwischen dem vorherigen und dem nächsten Sequenzpunkt soll der gespeicherte Wert eines skalaren Objekts höchstens einmal durch Auswertung eines Ausdrucks geändert werden. Darüber hinaus darf nur auf den vorherigen Wert zugegriffen werden, um den zu speichernden Wert zu bestimmen . Die Anforderungen dieses Absatzes müssen für jede zulässige Reihenfolge der Unterausdrücke eines vollständigen Ausdrucks erfüllt sein. Andernfalls ist das Verhalten undefiniert .
Der Code wird cmehrmals geändert, ohne dass ein Sequenzpunkt dazwischen liegt, und es wird nicht darauf zugegriffen, um den Wert des gespeicherten Objekts zu bestimmen. Dies ist ein klarer Verstoß gegen die obige Klausel, und daher ist das vom Standard vorgeschriebene Ergebnis undefiniertes Verhalten [Ref. 3] .