Apakah Memanggil Penghancur Anak Secara Eksplisit juga memanggil Penghancur Induk

Untuk manajer memori yang saya tulis dalam C++ sebagai bukti konsep, untuk melacak objek yang dialokasikan saya mengalokasikan memori dengan malloc() dalam suatu fungsi, kemudian mengembalikan pointer ke memori itu dan menggunakan operator penempatan baru. Kemudian, untuk melacak kapan objek tersebut dihapus, saya meneruskan pointer ke fungsi lain untuk memanggil free() pada pointer.

Namun, karena saya menggunakan free() dan bukan delete, konstruktor objek tidak dipanggil secara otomatis seperti biasanya, jadi saya harus memanggilnya sendiri. Selain itu, karena manajer memori dirancang untuk bekerja dengan objek apa pun, dapat dibayangkan (dan bahkan mungkin) bahwa pada suatu saat dalam masa pakainya, ia harus membebaskan objek yang berpotensi memiliki beberapa kelas induk atau berada jauh di dalam pohon warisan.

Solusi awal saya untuk ini adalah dengan memanggil destruktor objek dasar, yang akan memanggil semua destruktor anak (jika pertanyaan ini dapat dipercaya), tetapi karena objek secara harafiah dapat berupa apa saja dan memiliki rangkaian warisan apa pun, tidak ada cara untuk mengetahui kelas dasar yang sebenarnya untuk objek tersebut adalah.

Jadi pertanyaan saya adalah: apakah secara eksplisit memanggil destruktor kelas anak secara otomatis memanggil semua destruktor dasar juga, seperti dengan delete, atau apakah tidak ada cara untuk melakukan ini dengan mudah?


person sm81095    schedule 24.10.2014    source sumber
comment
Tidak ada perbedaan dalam perilaku panggilan otomatis destruktor jika dibandingkan dengan panggilan manual konstruktor (setidaknya, tidak ada yang saya ketahui). Namun, membuktikannya (dengan Standardese) mungkin rumit.   -  person dyp    schedule 25.10.2014
comment
Akan sangat mudah bagi Anda untuk menulis beberapa kode untuk mengetahuinya.   -  person Paul Rooney    schedule 25.10.2014
comment
@PaulRooney Itu tidak memberi Anda jaminan apa pun.   -  person dyp    schedule 25.10.2014


Jawaban (1)


Ya, itu dijamin. C++14 [kelas.dtor]/8:

Setelah mengeksekusi isi destruktor dan menghancurkan objek otomatis apa pun yang dialokasikan di dalam isi, destruktor untuk kelas X memanggil destruktor untuk anggota data non-statis non-varian langsung X, destruktor untuk kelas dasar langsung X dan, jika X adalah tipe kelas yang paling banyak diturunkan (12.6.2), destruktornya memanggil destruktor untuk kelas dasar virtual X.

Khususnya, untuk semua jenis T Anda selalu dapat melakukan ini:

void * addr = ::operator new(sizeof T);
T * p = ::new (addr) T(/* ctor args */);
p->~T();                                    // !
::operator delete(addr);

Atau, jika Anda tidak ingin memanggil pengalokasi:

{
    std::aligned_storage_t<sizeof(T), alignof(T)> storage;
    T * p = ::new (static_cast<void *>(std::addressof(storage))) T(/* args */);
    p->~T();
}
person Kerrek SB    schedule 24.10.2014
comment
Saya sebenarnya punya dua pertanyaan singkat tentang itu. 1. Ini untuk C++14, tetapi apakah ini juga dijamin untuk C++11 yang saya gunakan? 2. Ini mengatakan akan melakukan itu, tetapi tidak secara eksplisit mengatakan ini akan terjadi untuk panggilan eksplisit, jadi apakah itu dijamin atau ini hanya membicarakan delete saja? - person sm81095; 25.10.2014
comment
@sm81095: 1) ya, 2) ini tidak berbicara tentang delete; ini berbicara tentang destruktor. - person Kerrek SB; 25.10.2014
comment
Oke, luar biasa! Terima kasih atas jawaban yang cepat dan lugas. Saya akan melakukan banyak pengujian dengan ini, tapi karena ini bagian dari standar saya berharap semuanya berfungsi. - person sm81095; 25.10.2014
comment
@sm81095: Lupakan saja. Ini adalah bagian inti yang mendalam dari keseluruhan model objek bahasa sehingga sangat tidak terbayangkan bahwa kompiler akan melakukan kesalahan apa pun. - person Kerrek SB; 25.10.2014