Ausführungsreihenfolge des Operators neu und Argument des Konstruktors

9

Gibt die C ++ - Spezifikation die Reihenfolge operator newund den Konstruktor von Ain an new C(A())?
Das g ++ ließ die Reihenfolge sein A()-> new-> C(), aber clang ++ ließ es sein new->A() -> C().
Wird der Unterschied durch nicht angegebenes Verhalten verursacht?

g ++: 7.4.0 clang ++: 10.0.0

#include <iostream>
#include <cstdlib>

struct A {
    A() {
        std::cout << "call A()\n";
    }
};

struct C {
    C(A) {
        std::cout << "call S()\n";
    }

    void *operator new(size_t s) {
        std::cout << "call new()\n";
        return malloc(s);
    }
};

int main() {
    void *p = new C(A());
}
Eddie Kuo
quelle
3
Bauen Sie als C ++ 17, C ++ 14 oder früher?
StoryTeller - Unslander Monica
4
Zwei Anmerkungen: Sie haben dies mit "C" markiert, was deutlich zeigt, dass Sie die Beschreibung dieses Tags nicht gelesen haben. Tu es nicht. Nun fragen Sie nach "undefiniertem Verhalten" (UB). Dies ist ein Begriff, der vom C ++ - Standard verwendet wird, um Dinge zu markieren, bei denen alles passieren kann und die vermieden werden sollten. Es gibt auch "nicht spezifiziertes Verhalten", das wahrscheinlich näher an dem liegt, wonach Sie suchen, da der Code technisch in Ordnung ist und keine UB verursacht.
Ulrich Eckhardt
1
@Ulrich Eckhardt Vielen Dank für Ihren Vorschlag. Ich habe die beiden verwechselt.
Eddie Kuo

Antworten:

11

Clang ist richtig. Seit C ++ 17 ist die Ausführungsreihenfolge garantiert. [expr.new] / 19

Der Aufruf der Zuordnungsfunktion erfolgt vor der Auswertung der Ausdrücke im New-Initialisierer .

operator new(die Zuordnungsfunktion) soll zuerst aufgerufen werden, dann die Auswertung des Ausdrucks im New-Initialisierer (dh A()).

Vor C ++ 17 kann die Reihenfolge nicht garantiert werden. [expr.new] / 18 (C ++ 14)

Der Aufruf der Zuordnungsfunktion wird in Bezug auf die Auswertungen von Ausdrücken im Neuinitialisierer unbestimmt sequenziert .


Es scheint, dass gcc nicht mit C ++ 17 (und höher) übereinstimmt. Das Kompilieren mit gcc10 im C ++ 2a-Modus ergibt das gleiche Ergebnis.

songyuanyao
quelle