Czy ten program jest dobrze zdefiniowany, a jeśli nie, to dlaczego?Czy destruktor może rekursywnie?
#include <iostream>
#include <new>
struct X {
int cnt;
X (int i) : cnt(i) {}
~X() {
std::cout << "destructor called, cnt=" << cnt << std::endl;
if (cnt-- > 0)
this->X::~X(); // explicit recursive call to dtor
}
};
int main()
{
char* buf = new char[sizeof(X)];
X* p = new(buf) X(7);
p->X::~X(); // explicit call to dtor
delete[] buf;
}
Moje rozumowanie: chociaż invoking a destructor twice is undefined behavior, za 12,4/14, co mówi dokładnie to:
zachowanie jest niezdefiniowane jeżeli destruktor jest wywoływany dla obiektu którego żywotność zakończyła
Co wydaje się nie blokować wywołań rekursywnych. Podczas wykonywania destruktora dla obiektu czas życia obiektu jeszcze się nie skończył, dlatego nie jest to UB, aby ponownie wywołać destruktor. Z drugiej strony, 12,4/6 mówi:
Po wykonaniu ciała [...] przez destruktor dla klasy X nazywa destruktorów dla bezpośrednich członków X., destruktory dla bezpośredniej podstawy X. klas [ ...]
co oznacza, że po powrocie z rekurencyjnym wywołaniem destruktora, wszystkie destruktory członkowskie i base class zostaną powołani i nazywając je ponownie po powrocie do poprzedniego poziomu rekursji byłby UB . Dlatego klasa bez podstawy i tylko członkowie POD mogą mieć rekurencyjny destruktor bez UB. Czy mam rację?
To jest naprawdę dziwne, dlaczego kiedykolwiek chcesz wywołać rekurencję destruktora? – Andrey
Godne pytanie dla wuja Boba. –
Dlaczego, do cholery, kiedykolwiek chciałbyś to zrobić? – Puppy