Wenn wir drei Funktionen haben (foo, bar und baz), die so zusammengesetzt sind ...
foo(bar(), baz())
Gibt es eine Garantie des C ++ - Standards, dass der Balken vor baz ausgewertet wird?
Wenn wir drei Funktionen haben (foo, bar und baz), die so zusammengesetzt sind ...
foo(bar(), baz())
Gibt es eine Garantie des C ++ - Standards, dass der Balken vor baz ausgewertet wird?
Antworten:
Nein, es gibt keine solche Garantie. Es ist gemäß dem C ++ - Standard nicht spezifiziert.
Bjarne Stroustrup sagt es auch explizit in "The C ++ Programming Language", 3. Ausgabe, Abschnitt 6.2.2, mit einigen Überlegungen:
Besserer Code kann generiert werden, wenn die Reihenfolge der Ausdrucksbewertung nicht eingeschränkt ist
Obwohl sich dies technisch auf einen früheren Teil desselben Abschnitts bezieht, der besagt, dass die Reihenfolge der Bewertung von Teilen eines Ausdrucks ebenfalls nicht spezifiziert ist, d. H.
int x = f(2) + g(3); // unspecified whether f() or g() is called first
Es gibt keine festgelegte Reihenfolge für bar () und baz () - das einzige, was der Standard sagt, ist, dass beide ausgewertet werden, bevor foo () aufgerufen wird. Aus dem C ++ Standard, Abschnitt 5.2.2 / 8:
Die Reihenfolge der Bewertung der Argumente ist nicht angegeben.
bar
, dann Zeile 1 von baz
, dann Zeile 2 von bar
usw. nicht ausführen ), was ebenfalls hilfreich ist. :-)
Aus [5.2.2] Funktionsaufruf,
Die Reihenfolge der Bewertung der Argumente ist nicht angegeben. Alle Nebenwirkungen von Argumentausdrucksauswertungen werden wirksam, bevor die Funktion eingegeben wird.
Daher gibt es keine Garantie, bar()
die vorher ausgeführt wird baz()
, nur diese bar()
und baz()
wird vorher aufgerufen foo
.
Beachten Sie auch aus [5] Ausdrücken, dass:
Sofern nicht anders angegeben [z. B. Sonderregeln für
&&
und||
], ist die Reihenfolge der Bewertung von Operanden einzelner Operatoren und Unterausdrücke einzelner Ausdrücke sowie die Reihenfolge, in der Nebenwirkungen auftreten, nicht angegeben.
also auch wenn Sie wurden gefragt , ob bar()
vor laufen baz()
in foo(bar() + baz())
ist die Reihenfolge noch nicht spezifiziert.
&
, &&
Garantien von links nach rechts Auswertung: der zweite Operand , wenn der erste Operand nicht ausgewertet ist false
.“
C ++ 17 gibt die Auswertungsreihenfolge für Operatoren an, die bis C ++ 17 nicht angegeben wurden. Siehe die Frage Welche Garantien für die Evaluierungsreihenfolge werden von C ++ 17 eingeführt? Aber beachte deinen Ausdruck
foo(bar(), baz())
hat noch nicht spezifizierte Bewertungsreihenfolge.
In C ++ 11 finden Sie den relevanten Text in 8.3.6 Standardargumente / 9 (Hervorhebung meiner)
Standardargumente werden bei jedem Aufruf der Funktion ausgewertet. Die Reihenfolge der Auswertung von Funktionsargumenten ist nicht angegeben . Folglich dürfen Parameter einer Funktion nicht in einem Standardargument verwendet werden, selbst wenn sie nicht ausgewertet werden.
Dieselbe Sprache wird auch vom C ++ 14-Standard verwendet und befindet sich im selben Abschnitt .
Wie andere bereits ausgeführt haben, enthält der Standard keine Anleitung zur Reihenfolge der Bewertung für dieses spezielle Szenario. Diese Reihenfolge der Auswertung wird dann dem Compiler überlassen, und der Compiler hat möglicherweise eine Garantie.
Es ist wichtig, sich daran zu erinnern, dass der C ++ - Standard wirklich eine Sprache ist, um einen Compiler in die Erstellung von Assembly- / Maschinencode einzuweisen. Der Standard ist nur ein Teil der Gleichung. Wenn der Standard nicht eindeutig ist oder speziell für die Implementierung definiert ist, sollten Sie sich an den Compiler wenden und verstehen, wie er C ++ - Anweisungen in eine echte Maschinensprache übersetzt.
Wenn also die Reihenfolge der Auswertung eine Anforderung oder zumindest wichtig ist und es keine Anforderung ist, Cross-Compiler-kompatibel zu sein, untersuchen Sie, wie Ihr Compiler dies letztendlich zusammenfügen wird. Ihre Antwort könnte letztendlich dort liegen. Beachten Sie, dass der Compiler in Zukunft seine Methodik ändern könnte