Reihenfolge der Auswertung in C ++ - Funktionsparametern

88

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?

Clark Gaebel
quelle

Antworten:

100

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
Eli Bendersky
quelle
Ich kann diese Antwort in 8 Minuten akzeptieren ... Ich glaube, ich bleibe ein bisschen hier!
Clark Gaebel
4
Ja, aber besserer Code könnte SCHRIFTLICH (= sauberer) sein, wenn die Reihenfolge der Ausdrucksbewertung STRICT wäre, was im Allgemeinen viel wichtiger ist als die Codegenerierung. Siehe dieses Beispiel: stackoverflow.com/questions/43612592/… Also, Stroustrup.
Bill Kotsias
1
Wenn Sie etwas bestellen möchten, können Sie die Sequenzierung selbst durchführen. Andernfalls entstehen immer Kosten für etwas, das nicht immer (selten?) Von Bedeutung ist. Ich denke, die Politik, nicht für das zu bezahlen, was Sie nicht verwenden, ist das einzige, worüber sich die meisten C ++ - Programmierer einig sind.
Tweej
3
Sollte es nicht "nicht spezifiziertes Verhalten" statt "undefiniert" sein?
GoodDeeds
1
@ChrisDodd Das Herunterstimmen einer akzeptierten Antwort aufgrund der Verwendung des Wortes "undefiniert" vs. "nicht spezifiziert" fühlt sich für mich wie böswillige Pedanterie an ... Ich habe nicht gesagt, dass dies "undefiniertes Verhalten" ist, und ansonsten scheinen "undefiniert" und "nicht spezifiziert" gleichbedeutend? In jedem Fall wäre es produktiver gewesen, eine Änderung der Antwort vorzuschlagen, um dies zu diskutieren
Eli Bendersky,
20

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.


quelle
4
Die Tatsache, dass sie vor foo () ausgewertet werden, ist zumindest ein wenig beruhigend.
Bill Kotsias
1
@ BillKotsias Der Standard sagt auch, dass sich Funktionsaufrufe nicht überlappen können (dh eine Implementierung kann Zeile 1 von bar, dann Zeile 1 von baz, dann Zeile 2 von barusw. nicht ausführen ), was ebenfalls hilfreich ist. :-)
Melpomene
20

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.

Daniel Trebbien
quelle
4
Ein Beispiel für eine „besondere Note“ von [5,14] Logische UND - Verknüpfung: „ Im Gegensatz zu &, &&Garantien von links nach rechts Auswertung: der zweite Operand , wenn der erste Operand nicht ausgewertet ist false.“
Daniel Trebbien
2

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 .

R Sahu
quelle
0

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

Gelehrter Programmierer
quelle