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

9

La spécification C ++ spécifie-t-elle l'ordre operator newet le constructeur de Ain 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());
}
eddie kuo
la source
3
Construisez-vous en C ++ 17, C ++ 14 ou antérieur?
StoryTeller - Unslander Monica
4
Deux notes: vous avez marqué cela avec "C", ce qui montre clairement que vous n'avez pas lu la description de cette balise. Non. Maintenant, vous vous interrogez sur le "comportement indéfini" (UB). C'est un terme utilisé par la norme C ++ pour marquer les choses où tout peut arriver et qui doivent être évitées. Il existe également un "comportement non spécifié", qui est probablement plus proche de ce que vous recherchez, car le code est techniquement correct et ne cause pas d'UB.
Ulrich Eckhardt
1
@Ulrich Eckhardt Merci pour votre suggestion. J'ai mélangé les deux.
eddie kuo

Réponses:

11

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 des expressions dans le nouveau-initialiseur .

operator new(la fonction d'allocation) est supposée être invoquée d'abord, puis l'évaluation de l'expression dans le nouveau-initialiseur (ie 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 des expressions dans le nouvel initialiseur .


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.

songyuanyao
la source