Reihenfolge der Auswertung in C++-Funktionsparametern

Lesezeit: 4 Minuten

Wenn wir drei Funktionen (foo, bar und baz) haben, die so zusammengesetzt sind …

foo(bar(), baz())

Gibt es eine Garantie durch den C++-Standard, dass bar vor baz ausgewertet wird?

Reihenfolge der Auswertung in C Funktionsparametern
Eli Bendersky

Nein, eine solche Garantie gibt es nicht. Es ist gemäß dem C++-Standard nicht spezifiziert.

Bjarne Stroustrup sagt es auch explizit in “The C++ Programming Language”, 3. Auflage, Abschnitt 6.2.2, mit einigen Begründungen:

Besserer Code kann generiert werden, wenn die Reihenfolge der Ausdrucksauswertung nicht eingeschränkt ist

Obwohl sich dies technisch auf einen früheren Teil desselben Abschnitts bezieht, der besagt, dass die Reihenfolge der Auswertung von Teilen eines Ausdrucks ebenfalls nicht spezifiziert ist, dh

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

  • Ja, aber besserer Code könnte WRITTEN (= sauberer) sein, wenn die Auswertungsreihenfolge der Ausdrücke STRICT wäre, was im Allgemeinen viel wichtiger ist als die Codegenerierung. Siehe dieses Beispiel: stackoverflow.com/questions/43612592/… Also, Stroustrup.

    – Bill Kotsias

    25. April 2017 um 13:57 Uhr


  • Wenn es auf die Bestellung ankommt, können Sie die Sequenzierung selbst vornehmen. Andernfalls würden immer Kosten für etwas entstehen, das nicht immer (selten?) wichtig ist. Ich denke, dass die Richtlinie, nicht für das zu bezahlen, was Sie nicht verwenden, das einzige ist, dem die meisten C++-Programmierer zustimmen.

    – tweej

    2. Dezember 2017 um 9:53 Uhr

  • Sollte es nicht “nicht spezifiziertes Verhalten” statt “undefiniert” heißen?

    – Gute Taten

    6. Januar 2018 um 19:38 Uhr

  • @GoodDeeds Vor C++17, undefiniertes Verhalten, wenn die Funktionen Seiteneffekte am selben Speicherort verursachen. Nach C++17 ist es nicht spezifiziert.

    – Passant

    22. Juni 2018 um 16:53 Uhr

  • @ChrisDodd, der eine akzeptierte Antwort aufgrund der Verwendung des Wortes “undefiniert” vs. “nicht spezifiziert” ablehnt, 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” zu sein gleichbedeutend? In jedem Fall wäre es produktiver gewesen, eine Änderung der Antwort vorzuschlagen, um dies zu diskutieren

    – Eli Bendersky

    20. Juli 2018 um 13:19 Uhr

1647199208 506 Reihenfolge der Auswertung in C Funktionsparametern
Daniel Trebien

Von [5.2.2] Funktionsaufruf,

Die Reihenfolge der Bewertung der Argumente ist nicht festgelegt. Alle Seiteneffekte der Auswertung von Argumentausdrücken werden wirksam, bevor die Funktion eingegeben wird.

Daher gibt es dafür keine Garantie bar() wird vorher laufen baz()nur das bar() und baz() wird vorher angerufen foo.

Beachten Sie auch von [5] Ausdrücke, die:

außer wo vermerkt [e.g. special rules for && and ||]die Reihenfolge der Auswertung von Operanden einzelner Operatoren und Unterausdrücke einzelner Ausdrücke sowie die Reihenfolge, in der Seiteneffekte auftreten, ist nicht festgelegt.

also selbst wenn Sie fragen würden, ob bar() wird vorher laufen baz() in foo(bar() + baz())die Reihenfolge ist noch nicht festgelegt.

  • Ein Beispiel für einen “besonderen Hinweis” von [5.14] Logischer UND-Operator: „Anders &, && garantiert Links-nach-rechts-Auswertung: Der zweite Operand wird nicht ausgewertet, wenn der erste Operand es ist false.”

    – Daniel Trebbien

    29. Mai 2010 um 12:31 Uhr

Es gibt keine festgelegte Reihenfolge für bar() und baz() – das einzige, was der Standard sagt, ist, dass sie beide ausgewertet werden, bevor foo() aufgerufen wird. Aus dem C++-Standard, Abschnitt 5.2.2/8:

Die Reihenfolge der Bewertung der Argumente ist nicht festgelegt.

  • Die Tatsache, dass sie vor foo() ausgewertet werden, ist zumindest etwas beruhigend.

    – Bill Kotsias

    25. April 2017 um 13:58 Uhr

  • @BillKotsias Der Standard besagt auch, dass sich Funktionsaufrufe nicht überlappen dürfen (dh eine Implementierung kann Zeile 1 von nicht ausführen bardann Zeile 1 von bazdann Zeile 2 von bar, etc.), was auch schön ist. 🙂

    – Melpomen

    31. Juli 2019 um 21:04 Uhr

C++17 gibt die Auswertungsreihenfolge für Operatoren an, die bis C++17 nicht angegeben war. Siehe die Frage Was sind die von C++17 eingeführten Garantien für die Bewertungsreihenfolge? Aber achte auf deinen Gesichtsausdruck

foo(bar(), baz())

hat noch nicht spezifizierte Auswertungsreihenfolge.

In C++11 findet sich der entsprechende Text in 8.3.6 Standardargumente/9 (Hervorhebung von mir)

Standardargumente werden bei jedem Aufruf der Funktion ausgewertet. Die Reihenfolge der Auswertung von Funktionsargumenten ist nicht festgelegt. Folglich dürfen Parameter einer Funktion nicht in einem Standardargument verwendet werden, auch wenn sie nicht ausgewertet werden.

Dieselbe Wortwahl wird auch vom C++14-Standard verwendet und ist unter zu finden der gleiche Abschnitt.

Reihenfolge der Auswertung in C Funktionsparametern
Gelehrter Programmierer

Wie andere bereits betont haben, gibt die Norm keine Anleitung zur Bewertungsreihenfolge für dieses spezielle Szenario. Diese Auswertungsreihenfolge wird dann dem Compiler überlassen, und der Compiler hat möglicherweise eine Garantie.

Es ist wichtig, sich daran zu erinnern, dass der C++-Standard eigentlich eine Sprache ist, um einen Compiler anzuweisen, Assembly-/Maschinencode zu erstellen. Der Standard ist nur ein Teil der Gleichung. Wenn der Standard mehrdeutig ist oder eine spezifische Implementierung definiert ist, sollten Sie sich an den Compiler wenden und verstehen, wie er C++-Anweisungen in echte Maschinensprache übersetzt.

Wenn also die Reihenfolge der Auswertung eine Voraussetzung oder zumindest wichtig ist und Cross-Compiler-Kompatibilität keine Voraussetzung ist, untersuchen Sie, wie Ihr Compiler dies letztendlich zusammenfügt, Ihre Antwort könnte letztendlich dort liegen. Beachten Sie, dass der Compiler seine Methodik in Zukunft ändern könnte

998800cookie-checkReihenfolge der Auswertung in C++-Funktionsparametern

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

Privacy policy