Ordem de execução do operador new e argumento do construtor

9

A especificação C ++ especifica a ordem operator newe o construtor de Ain new C(A()).
O g ++ deixou a ordem como A()-> new-> C(), mas o clang ++ deixou new- A()- - -> C().
A diferença é causada por comportamento não especificado?

g ++: 7.4.0 cl +++: 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
fonte
3
Você está construindo como C ++ 17, C ++ 14 ou anterior?
StoryTeller - Unslander Monica
4
Duas notas: você marcou "C", o que mostra claramente que você não leu a descrição dessa tag. Não. Agora, você pergunta sobre "comportamento indefinido" (UB). Este é um termo usado pelo padrão C ++ para marcar coisas onde tudo pode acontecer e que deve ser evitado. Também existe um "comportamento não especificado", provavelmente mais próximo do que você procura, porque o código é tecnicamente correto e não causa UB.
Ulrich Eckhardt
11
@Ulrich Eckhardt Obrigado pela sua sugestão. Eu misturei os dois.
precisa

Respostas:

11

Clang está correto. Desde C ++ 17, a ordem de execução é garantida. [expr.new] / 19

A chamada da função de alocação é sequenciada antes das avaliações de expressões no novo inicializador .

operator new(a função de alocação) deve ser chamada primeiro, depois a avaliação da expressão no novo inicializador (ie A()).

Antes do C ++ 17, o pedido não era garantido. [expr.new] / 18 (C ++ 14)

A invocação da função de alocação é sequenciada indeterminadamente com relação às avaliações de expressões no novo inicializador .


Parece que o gcc não está em conformidade com o C ++ 17 (e posterior); compilar com o gcc10 no modo C ++ 2a fornece o mesmo resultado.

songyuanyao
fonte