• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

std::unique_ptr i dziedziczony destruktor

0 głosów
132 wizyt
pytanie zadane 12 sierpnia 2021 w C i C++ przez Pawel1995 Gaduła (3,160 p.)

Cześć mam problem z zrozumieniem fragmentu kodu z "testu rekrutacyjnego"

Otóż mamy taki kod:

#include <iostream>

struct A
{
    ~A() { printf("~A"); }
};

struct B
    : A
{
    ~B() { printf("~B"); };
};

int main()
{
    std::unique_ptr < A > x(new B);  //wariant 1
    return 0;
}

Moje pytanie brzmi czemu wynik tego to "~A" zamiast "~B~A" jak bym się spodziewał?

 

Kiedy w szablon wsadzam klasę pochodną:

std::unique_ptr < B > x(new B); //wariant 2

Wynik jest taki jak chcę. Rozumiem takie zachowanie kiedy by była tylko klasa bazowa wywołana:

std::unique_ptr < A > x(new A); //wariant 3

Ale jednak w tym wariancie 1 jest tworzony obiekt "B", więc dlaczego nie jest wywoływany jego [obiektu "B"] destruktor?

2 odpowiedzi

0 głosów
odpowiedź 12 sierpnia 2021 przez TOM_CPP Pasjonat (22,320 p.)
wybrane 12 sierpnia 2021 przez Pawel1995
 
Najlepsza

Destruktor w klasie bazowej powinien być wirtualny. Ta informacja używana jest przez kompilator w momencie usunięcia obiektu za pomocą wskaźnika do klasy bazowej. Kompilator widząc słowo virtual, wywoła odpowiednią/poprawną sekwencję destruktorów, zdefiniowaną przez dziedziczenie. Gdy tego słowa nie będzie, potraktuje obiekt jako bazowy, wywołując tylko jego destruktor, co prowadzi do UB.

Jako ciekawostka - jeżeli użyjemy shared_ptr zamiast unique_ptr, kod wykona się prawidłowo.

https://godbolt.org/z/981M54h5h

komentarz 13 sierpnia 2021 przez j23 Mędrzec (172,940 p.)

Jako ciekawostka (...)

Zapewne dlatego, że w shared_ptr deleter "wędruje" razem ze wskaźnikiem. W przypadku unique_ptr deleter jest ustawiony na sztywno dla typu T.

0 głosów
odpowiedź 12 sierpnia 2021 przez adrian17 Ekspert (319,660 p.)
Bo zapomniałeś uczynić destruktor wirtualnym :)
komentarz 12 sierpnia 2021 przez Pawel1995 Gaduła (3,160 p.)
ale jednak kiedy stosuje //wariant 2 to wszystko działa jak trzeba mimo że nie mam destruktora wirtualnego.
komentarz 12 sierpnia 2021 przez adrian17 Ekspert (319,660 p.)
Tak, bo w wariancie 2, wiadomo że wskaźnik wskazuje na obiekt klasy B, więc wiadomo żeby wywołać destruktor B. W innych, wskaźnik wie tylko że wskazuje na A, więc nie ma skąd wiedzieć żeby wywołać destruktor B - po to są funkcje wirtualne.

Podobne pytania

0 głosów
2 odpowiedzi 167 wizyt
0 głosów
1 odpowiedź 91 wizyt
+1 głos
2 odpowiedzi 351 wizyt

87,946 zapytań

136,526 odpowiedzi

304,410 komentarzy

58,313 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...