Bestellen einer Initialisierung in C, C++

Lesezeit: 4 Minuten

Betrachten Sie die folgenden Initialisierungen:

/* C, C++ */
int a[] = { f(), g() };
struct { int x, y } foo = { f(), g() };

/* C++ */
struct goo { goo(int x, int y);  };

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */
goo d ( f(), g() );

Ist die Reihenfolge der Ausführung f() und g() in irgendeiner durch C- und C++-Standards spezifizierten Zeile?

Benutzer-Avatar
Vlad aus Moskau

In all diesen beiden Fällen

goo b = { f(), g() };
goo c { f(), g() };    /* C++11 */

die Auswertungsreihenfolge wird von links nach rechts bestimmt und alle Nebeneffekte sollen vor dem nächsten Initialisierer angewendet werden.

Aus dem C++-STANDARD

4 Innerhalb der Initialisierungsliste einer geklammerten Initialisierungsliste werden die Initialisierungsklauseln, einschließlich aller, die aus Paketerweiterungen (14.5.3) resultieren, in der Reihenfolge ausgewertet, in der sie erscheinen. Das heißt, jede Wertberechnung und Nebenwirkung, die einer gegebenen Initialisierungsklausel zugeordnet ist, wird vor jeder Wertberechnung und Nebenwirkung geordnet, die irgendeiner Initialisierungsklausel zugeordnet ist, die ihr in der durch Kommas getrennten Liste der Initialisierungsliste folgt.

In C gibt es jedoch eine andere Regel

Die Auswertungen der Initialisierungslistenausdrücke sind in Bezug aufeinander unbestimmt sequenziert, und somit ist die Reihenfolge, in der irgendwelche Nebeneffekte auftreten, unbestimmt.

  • Wenn ich darüber nachdenke, denke ich, dass alle bis auf die letzten in C ++ 11 so sind.

    – Chris

    19. März 2014 um 19:09 Uhr

  • @Vlad: Was ist mit den ersten beiden Zeilen in C++11? Die Reihenfolge steht nicht fest?

    Benutzer1150105

    19. März 2014 um 19:18 Uhr

  • @Corvus Der erste Ausdruck int a[] = {f(), g()}; erfüllt die Regel. Berücksichtigen Sie, dass GCC 4,8,2 einen Fehler hat. Der zweite Ausdruck soll nicht kompiliert werden.:) Es gibt keinen Deklarator.

    – Vlad aus Moskau

    19. März 2014 um 19:21 Uhr


  • @Vlad: Entschuldigung für den zweiten Ausdruck. Ich habe es bearbeitet.

    Benutzer1150105

    19. März 2014 um 19:32 Uhr

  • @hackks: Welche Regel macht es bestimmt? goo ddie keine geklammerte Init-Liste hat?

    – Ben Voigt

    19. März 2014 um 20:27 Uhr

Benutzer-Avatar
hackt

Ist die Ausführungsreihenfolge f() und g() in irgendeiner Zeile durch C- und C++-Standards spezifiziert?

In C, Nein. Sie können in beliebiger Reihenfolge auswerten.

C11 6.7.9 Initialisierung

Die Auswertungen der Initialisierungslistenausdrücke sind in unbestimmter Reihenfolge zueinander und damit Die Reihenfolge, in der Nebenwirkungen auftreten, ist nicht angegeben,152).

Während C++11 sagt, dass die Reihenfolge der Auswertung deterministisch ist.

8.5.4:4 Listen-Initialisierung

Innerhalb der Initialisierungsliste einer geklammerten Initialisierungsliste werden die Initialisierungsklauseln, einschließlich aller, die aus Paketerweiterungen (14.5.3) resultieren, werden in der Reihenfolge ihres Erscheinens ausgewertet. Das heißt, jede Wertberechnung und Nebenwirkung, die einer gegebenen Initialisierungsklausel zugeordnet ist, wird vor jeder Wertberechnung und Nebenwirkung geordnet, die irgendeiner Initialisierungsklausel zugeordnet ist, die ihr in der durch Kommas getrennten Liste der Initialisierungsliste folgt.


152) Insbesondere muss die Auswertungsreihenfolge nicht dieselbe sein wie die Reihenfolge der Unterobjektinitialisierung.

  • Wo sind f und g definiert? Ich sehe es nicht

    – Ingenieur2021

    19. März 2014 um 19:04 Uhr


  • @GIJoe; Angenommen, der bereitgestellte Code ist nur ein Code-Snippet 🙂

    – Hacken

    19. März 2014 um 19:06 Uhr

  • Könnte evtl. an den fehlenden Hinweisen und der Kürze der Antwort liegen.

    – Manu343726

    19. März 2014 um 19:13 Uhr

  • @Convus das ist nicht sein Problem, denke ich. Das ist das Problem eines OP, weil diese Art von Frage für verschiedene Sprachen getaggt wird (möglicherweise denken, dass C und C ++ dieselbe Sprache sind).

    – Manu343726

    19. März 2014 um 19:20 Uhr


  • Aber der Initialisierer von goo d hat keine geklammerte Init-Liste, daher gilt für diese die zitierte C++-Regel nicht.

    – Ben Voigt

    19. März 2014 um 20:27 Uhr

Benutzer-Avatar
ouah

Nein, in C ist die Auswertungsreihenfolge der Initialisierer nicht festgelegt:

(C11, 6.7.9p23) “Die Auswertungen der Initialisierungslistenausdrücke sind in unbestimmter Reihenfolge zueinander und daher ist die Reihenfolge, in der irgendwelche Seiteneffekte auftreten, nicht spezifiziert.152)”

152) Insbesondere muss die Auswertungsreihenfolge nicht dieselbe sein wie die Reihenfolge der Unterobjektinitialisierung.

In C++ ist das Verhalten anders, und die Initialisierer werden in der Reihenfolge ausgewertet, in der sie erscheinen (C++11, 8.5.4p4).

Benutzer-Avatar
iavr

In C++11 ist der relevante Teil Absatz 4 von 8.5.4 Listen-Initialisierung

Innerhalb der Initialisierungsliste von a geklammerte Init-Listedas Initialisierungsklauselneinschließlich aller, die aus Paketerweiterungen (14.5.3) resultieren, werden in der Reihenfolge ihres Erscheinens ausgewertet. Das heißt, jede Wertberechnung und Nebenwirkung, die mit einer bestimmten verbunden ist Initialisierungsklausel vor jeder Wertberechnung sequenziert und mit irgendeiner Nebenwirkung verbunden ist Initialisierungsklausel das folgt in der durch Kommas getrennten Liste der Initialisierungsliste. [ Note: This evaluation ordering holds regardless of the semantics of the initialization; for example, it applies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. — end note ]

Die Reihenfolge der Bewertung ist also links nach rechts.

Jedoch Beachten Sie, dass leider aufgrund von a Insekt seit mindestens Version 4.7.0 wertet GCC in umgekehrter Reihenfolge aus, rechts nach links. Wenn Sie also unerwartete Ergebnisse erhalten, kann dies ein Grund sein.

1175440cookie-checkBestellen einer Initialisierung in C, C++

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

Privacy policy