Perintah eksekusi operator baru dan argumen konstruktor

9

Apakah spesifikasi C ++ menentukan urutan operator newdan konstruktor Adalam new C(A()).
G ++ membiarkan urutannya menjadi A()-> new-> C(), tetapi clang ++ biarkan saja new-> A()-> C().
Apakah perbedaan disebabkan oleh perilaku yang tidak ditentukan?

g ++: 7.4.0 dentang ++: 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
sumber
3
Apakah Anda membangun sebagai C ++ 17, C ++ 14 atau sebelumnya?
StoryTeller - Unslander Monica
4
Dua catatan: Anda memberi tag ini dengan "C", yang jelas menunjukkan Anda tidak membaca deskripsi tag itu. Jangan. Sekarang, Anda bertanya tentang "perilaku tidak terdefinisi" (UB). Ini adalah istilah yang digunakan oleh standar C ++ untuk menandai hal-hal di mana segala sesuatu dapat terjadi dan yang harus dihindari. Ada juga "perilaku tidak spesifik", yang mungkin lebih dekat dengan apa yang Anda cari, karena kode ini baik-baik saja secara teknis dan tidak menyebabkan UB.
Ulrich Eckhardt
1
@Ulrich Eckhardt Terima kasih atas saran Anda. Saya mencampuradukkan keduanya.
eddie kuo

Jawaban:

11

Dentang benar. Sejak C ++ 17 perintah eksekusi dijamin. [expr.new] / 19

Doa fungsi alokasi diurutkan sebelum evaluasi ekspresi di inisialisasi baru .

operator new(fungsi alokasi) seharusnya dipanggil terlebih dahulu, kemudian evaluasi ekspresi di-inisialisasi baru (yaitu A()).

Sebelum C ++ 17, pesanan tidak dijamin. [expr.new] / 18 (C ++ 14)

Doa dari fungsi alokasi secara tidak pasti diurutkan sehubungan dengan evaluasi ekspresi dalam inisialisasi baru .


Tampaknya gcc tidak sesuai dengan C ++ 17 (dan yang lebih baru); kompilasi dengan gcc10 dalam mode C ++ 2a memberikan hasil yang sama.

songyuanyao
sumber