Reihenfolge der Auswertung von Argumenten mit std::cout
Lesezeit: 4 Minuten
FehlgeschlagenDev
Hallo zusammen, ich bin heute über diesen Code gestolpert und bin verwirrt, was genau passiert und insbesondere in welcher Reihenfolge:
Code:
#include <iostream>
bool foo(double & m)
{
m = 1.0;
return true;
}
int main()
{
double test = 0.0;
std::cout << "Value of test is : \t" << test << "\tReturn value of function is : " << foo(test) << "\tValue of test : " << test << std::endl;
return 0;
}
Die Ausgabe ist:
Value of test is : 1 Return value of function is : 1 Value of test : 0
Wenn ich das sehe, würde ich annehmen, dass irgendwie das am weitesten rechts stehende Argument vor dem Aufruf der Funktion ausgegeben wird. Das ist also eine Rechts-Links-Bewertung?? Während des Debuggens scheint es jedoch, dass die Funktion vor der Ausgabe aufgerufen wird, was ich erwarten würde. Ich verwende Win7 und MSVS 2010. Jede Hilfe ist willkommen!
Matteo Italien
Die Auswertungsreihenfolge von Elementen in einem Ausdruck ist nicht festgelegt (mit Ausnahme einiger sehr spezieller Fälle, wie z && und || Operatoren und der ternäre Operator, die einführen Sequenzpunkte); das ist also nicht garantiert test wird vorher oder nachher ausgewertet foo(test) (was es modifiziert).
Wenn Ihr Code auf einer bestimmten Auswertungsreihenfolge beruht, ist die einfachste Methode, diese zu erhalten, den Ausdruck in mehrere getrennte Anweisungen aufzuteilen.
Kennen Sie einen Trick mit || oder && eine bestimmte Auswertungsreihenfolge durchzusetzen in a << Kette?
– alfC
20. Mai 2016 um 23:12 Uhr
Nein, aber ich kenne einen Trick ; und die Stream-Variable nach einem Zeilenumbruch wiederholen 😉
– Matteo Italien
21. Mai 2016 um 3:25 Uhr
Vielleicht wäre das Aktualisieren dieser Antwort mit den im C++17-Standard eingeführten Änderungen hilfreich für Leute, die in Zukunft darauf stoßen: stackoverflow.com/a/50361417/9385966
– flegar
16. Mai 2018 um 2:12 Uhr
Die Antwort auf diese Frage hat sich in C++17 geändert.
Die Auswertung überladener Operatoren erfolgt jetzt genauso wie bei integrierten Operatoren (C++17 [over.match.oper]/2).
Außerdem die <<, >> und tiefstellende Operatoren haben jetzt den linken Operanden zuvor sequenziert rechts, und der Postfix-Ausdruck eines Funktionsaufrufs ist zuvor sequenziert Bewertung der Argumente.
(Die anderen binären Operatoren behalten ihre bisherige Reihenfolge bei, z + ist noch nicht sequenziert).
Der Code in der Frage muss also jetzt ausgegeben werden Value of test is : 0 Return value of function is : 1 Value of test : 1. Aber der Rat „Tu das nicht“ ist immer noch vernünftig, da es einige Zeit dauern wird, bis alle auf C++17 aktualisieren.
Die Reihenfolge der Auswertung ist nicht festgelegt. Es ist nicht von links nach rechts, von rechts nach links oder irgendetwas anderes.
Dies ist die gleiche Situation wie im Beispiel mit dem operator+-Beispiel:
Betrachten Sie zwei Funktionen f() und g(). In C und C++ ist die + -Operator ist keinem Sequenzpunkt zugeordnet und daher im Ausdruck enthalten f()+g() das ist auch möglich f() oder g() wird zuerst ausgeführt.
Aufgrund der damit verbundenen Nebenwirkungen müssen integrierte Inkrement- und Dekrementoperatoren mit Vorsicht verwendet werden, um undefiniertes Verhalten aufgrund von Verletzungen von Sequenzierungsregeln zu vermeiden.
und im Abschnitt über Sequenzierungsregeln können Sie Folgendes lesen:
Undefiniertes Verhalten:
1) Wenn eine Nebenwirkung auf ein skalares Objekt relativ zu einer anderen Nebenwirkung auf dasselbe skalare Objekt nicht sequenziert ist, ist das Verhalten undefiniert.
i = ++i + 2; // undefined behavior until C++11
i = i++ + 2; // undefined behavior until C++17
f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i); // undefined behavior until C++17, unspecified after C++17
i = ++i + i++; // undefined behavior
2) Wenn ein Nebeneffekt auf ein skalares Objekt relativ zu einer Wertberechnung unter Verwendung des Werts desselben skalaren Objekts nicht sequenziert ist, ist das Verhalten undefiniert.
cout << i << i++; // undefined behavior until C++17
a[i] = i++; // undefined behavior until C++17
n = ++i + i; // undefined behavior
9942100cookie-checkReihenfolge der Auswertung von Argumenten mit std::coutyes