Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Smart pointers and virtual destructors

Ostatnio zmodyfikowano 2022-08-15 22:23
Autor Wiadomość
krystian123456
Temat założony przez niniejszego użytkownika
Smart pointers and virtual destructors
» 2022-08-12 17:00:58
Czy jest sens pisać w ogóle  destruktory w klasach a tym bardziej jako wirtualnie jeśli używamy inteligentnych wskaźników, przez co pamięć jest i tak czyszczona automatycznie ?
P-179597
DejaVu
» 2022-08-13 12:55:14
Inteligentne wskaźniki 'nie gwarantują' usunięcia całej pamięci. One gwarantują tylko, że destruktor zostanie automatycznie wywołany, gdy ostatnie odwołanie do instancji obiektu przestanie istnieć.
C/C++
class X
{
public:
   
X()
        :
m_x( new int )
   
{ }
   
private:
   
int * m_x;
};

Ta klasa będzie generowała Ci memory leak niezależnie od tego czy użyjesz ją na stosie czy stercie. Nie ważne czy opakujesz ją w std::shared_ptr<> czy nie.
C/C++
{
   
X x;
} //Obiekt 'x' w tym miejscu zostanie zniszczony + destruktor zostanie wywołany, ale m_x miało zarezerwowaną pamięć dynamicznie, więc... masz memory leaka.

Dokładnie taki sam efekt (memory leak) uzyskasz pisząc:
C/C++
{
   
std::shared_ptr < X > refX = std::make_shared < X >();
}
//Obiekt zostanie zniszczony, gdy ostatnie odwołanie do obiektu zniknie. Destruktor zostanie wywołany, ale m_x miało zarezerwowaną pamięć dynamicznie, więc tak czy inaczej masz memory leaka.

/edit:
Nawiązując do 'wirtualnych destruktorów' - one również są potrzebne po to, aby właściwy destruktor się wywołał. Jak tego nie będziesz robił, to również prosisz się o memory leaki. Przykład:
C/C++
class Bazowa
{
public:
   
Bazowa() { }
}
;

class Pochodna
    : Bazowa
{
public:
   
Pochodna()
        :
m_x( new int )
   
{ }
   
~Pochodna() { delete m_x; }
   
private:
   
int * m_x;
}

int main()
{
   
std::shared_ptr < Bazowa > refX = std::make_shared < Pochodna >();
} // Brak wirtualnego destruktora w klasie 'Bazowa' powoduje, że nie zostanie wywołany destruktor '~Pochodna', więc... znów masz memory leak.

C/C++
int main()
{
   
// UWAGA: inna definicja shared_ptr:
   
std::shared_ptr < Pochodna > refX = std::make_shared < Pochodna >();
} // W tym miejscu NIE BĘDZIE memory leak-a, bo wywoła się poprawny destruktor z racji, że typem shared_ptr jest klasa 'Pochodna', a nie 'Bazowa'

Natomiast, aby w pierwszym scenariuszu nie było memory leak-a, to wystarczy do klasy bazowej dopisać wirtualny destruktor:
C/C++
class Bazowa
{
public:
   
Bazowa() { }
   
virtual ~Bazowa() { } //TO JEST WAŻNE
};
P-179598
krystian123456
Temat założony przez niniejszego użytkownika
» 2022-08-14 00:25:09
A co gdyby zamiast int* m_x , zastąpić go też inteligentnym wskaźnikiem , czy zmieniło by to wiele ?

C/C++
class Bazowa
{
public:
   
Bazowa() { }
}
;

class Pochodna
    : public Bazowa
{
public:
   
Pochodna()
        :
m_x( std::make_shared < int >() )
   
{ }
   
~Pochodna() { }
   
private:
   
std::shared_ptr < int > m_x;
};

int main()
{
   
std::shared_ptr < Bazowa > refX = std::make_shared < Pochodna >();
   
return 0;
}
P-179603
DejaVu
» 2022-08-14 00:49:50
Skoro destruktor ~Pochodna się nie wywoła to spodziewaj się memory leaków. Jak nie jesteś pewien co się stanie to możesz zamiast typu 'int' podstawić klasę, która w destruktorze wypisuje wartość. Niemniej jednak sprawdzisz zachowanie danego kompilatora, a nie standardu.

Skup się na pisaniu poprawnego kodu, a nie zastanawiaj się 'czy kod się zachowa dobrze, jak źle go będę pisał'. Nawet jak dziś zadziała dobrze, to za rok projekt może Ci się zacząć składać w różnych miejscach i potem będziesz tracił niepotrzebnie czas.
P-179605
krystian123456
Temat założony przez niniejszego użytkownika
» 2022-08-14 11:19:23
Czyli rozumiem że mimo wszystko i tak powinien być tam destruktor wirtualny ? A jeszcze czy istnieją przykłady gdzie nie używać inteligentnych wskaźników, tylko trzeba zwykłych?
P-179607
pekfos
» 2022-08-14 13:29:08
A jeszcze czy istnieją przykłady gdzie nie używać inteligentnych wskaźników, tylko trzeba zwykłych?
Zawsze gdy nie Ty odpowiadasz za zwolnienie pamięci.
P-179609
krystian123456
Temat założony przez niniejszego użytkownika
» 2022-08-15 22:23:10
Dziękuje za pomoc
P-179613
« 1 »
  Strona 1 z 1