Mam, class A
który używa alokacji pamięci sterty dla jednego ze swoich pól. Klasa A jest tworzona i przechowywana jako pole wskaźnika w innej klasie ( class B
.
Kiedy skończę z obiektem klasy B, wzywam delete
, który, jak przypuszczam, wywołuje destruktor… Ale czy to wywołuje również destruktor klasy A?
Edytować:
Z odpowiedzi wyciągam to (edytuj, jeśli są nieprawidłowe):
delete
instancji B wywołuje B :: ~ B ();- który dzwoni
A::~A();
A::~A
powinny jawniedelete
wszystkie przypisane do sterty zmienne składowe obiektu A;- Na koniec blok pamięci przechowujący wspomnianą instancję klasy B jest zwracany na stertę - gdy nowy został użyty, najpierw przydzielił blok pamięci na stercie, a następnie wywołał konstruktory, aby go zainicjować, teraz po wywołaniu wszystkich destruktorów w celu sfinalizowania obiektu blok, w którym rezydował obiekt, jest zwracany na stertę.
źródło
++
na nim operatora. Zastanawiam się więc, czy wskaźnik, który wskazuje środek danych klasy, nadal działa.Kiedy wywołujesz delete na wskaźniku przydzielonym przez new, zostanie wywołany destruktor obiektu wskazywanego.
źródło
Nazywa się „destruktorem”, a nie „dekonstruktorem”.
Wewnątrz destruktora każdej klasy musisz usunąć wszystkie inne zmienne składowe, którym przydzielono nowe.
edytuj: Aby wyjaśnić:
Powiedz, że masz
Przydzielenie wystąpienia B, a następnie usunięcie jest czyste, ponieważ to, co B przydzieli wewnętrznie, zostanie również usunięte w destruktorze.
Ale instancje klasy C będą przeciekać pamięć, ponieważ przydziela instancję A, której nie zwalnia (w tym przypadku C nie ma nawet destruktora).
źródło
Jeśli masz zwykły wskaźnik (
A*
), to destruktor nie zostanie wywołany (i naA
przykład pamięć też nie zostanie zwolniona), chyba że zrobisz todelete
jawnie wB
destruktorze. Jeśli chcesz automatycznego niszczenia, spójrz na inteligentne wskazówki, takie jakauto_ptr
.źródło
Powinieneś samodzielnie usunąć A w destruktorze B.
źródło
Kiedy robisz:
Destruktor zostanie wywołany tylko wtedy, gdy twoja klasa bazowa zawiera słowo kluczowe virtual.
Wtedy, gdybyś nie miał wirtualnego destruktora, wywołano by tylko ~ B (). Ale ponieważ masz wirtualny destruktor, najpierw zostanie wywołana ~ D (), a następnie ~ B ().
Żaden członek B lub D przydzielony na stercie nie zostanie zwolniony, chyba że zostanie ich jawnie usunięty. Usunięcie ich spowoduje również wywołanie ich destruktora.
źródło
Masz coś takiego
Jeśli następnie zadzwonisz
delete b;
, nic się nie stanie i masz wyciek pamięci. Próba zapamiętaniadelete b->a;
nie jest dobrym rozwiązaniem, ale jest kilka innych.To jest destruktor dla B, który usunie plik. (Jeśli a jest równe 0, to usunięcie nic nie daje. Jeśli a nie jest równe 0, ale nie wskazuje na pamięć z nowego, otrzymujesz uszkodzenie sterty).
W ten sposób nie masz a jako wskaźnika, ale raczej auto_ptr <> (shared_ptr <> lub inne inteligentne wskaźniki) i jest automatycznie usuwane, gdy b jest.
Każdy z tych sposobów działa dobrze i użyłem obu.
źródło
Zastanawiałem się, dlaczego nie wywołano destruktora mojej klasy. Powodem było to, że zapomniałem dołączyć definicję tej klasy (#include "class.h"). Miałem tylko deklarację typu „klasa A”; a kompilator był z tego zadowolony i pozwól mi zadzwonić do "delete".
źródło
Nie. Wskaźnik zostanie usunięty. Powinieneś wywołać delete na A explicite w destruktorze B.
źródło
Destruktor obiektu klasy A zostanie wywołany tylko wtedy, gdy dla tego obiektu zostanie wywołane usuwanie. Pamiętaj, aby usunąć ten wskaźnik w destruktorze klasy B.
Aby uzyskać więcej informacji na temat tego, co dzieje się, gdy wywoływane jest usuwanie na obiekcie, zobacz: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9
źródło
nie, nie wywoła destruktora dla klasy A, powinieneś wywołać go jawnie (jak powiedział PoweRoy), usuń linię 'delete ptr;' na przykład, aby porównać ...
źródło