web-dev-qa-db-fra.com

Ordre d'exécution de l'opérateur nouveau et argument du constructeur

La spécification C++ spécifie-t-elle l'ordre operator new Et le constructeur de A dans new C(A()).
Le g ++ laisse l'ordre être A() -> new -> C(), mais clang ++ le laisse être new -> A() -> C().
La différence est-elle causée par un comportement non spécifié?

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());
}
9
eddie kuo

Clang a raison. Depuis C++ 17, l'ordre d'exécution est garanti. [expr.new]/19

L'invocation de la fonction d'allocation est séquencée avant les évaluations d'expressions dans le new-initializer .

operator new (La fonction d'allocation) est supposé être appelé en premier, puis l'évaluation de l'expression dans le nouveau initialiseur (c'est-à-dire A()).

Avant C++ 17, la commande n'est pas garantie. [expr.new]/18 (C++ 14)

L'invocation de la fonction d'allocation est séquencée de façon indéterminée par rapport aux évaluations d'expressions dans le new-initializer .


Il semble que gcc ne soit pas conforme à C++ 17 (et versions ultérieures); la compilation avec gcc10 en mode C++ 2a donne le même résultat.

11
songyuanyao