shared_ptr free memory

0

Witam,

Był podobny temat, ale 2 lata temu i dlatego decydowałem się na nowy wątek.

 using namespace std;

class B;
class A
{
public:
    A() {};
    ~A()
    {
        cout << " A is destroyed" << endl;
    }
};
class B
{
public:
    B() : m_sptrA(nullptr) { };
    ~B()
    {
        cout << " B is destroyed" << endl;
    }
    shared_ptr<A> m_sptrA;
};
//***********************************************************
void main()
{
    {
        shared_ptr<B> sptrB(new B);
        shared_ptr<A> sptrA(new A);

        //With this line order of destructors is replaced. 
        //sptrB->m_sptrA = sptrA; 

    }
    getchar();
}

Kiedy shared_ptr sptrA zostaje przypisane do pola m_sptrA, kolejność wywoływania destruktów zostaje zamieniona. Czy ktoś potrafiłby wytłumaczyć jaki mechanizm się za tym kryje ?

1

Mechanizm iluzji. Kolejność wywołania destruktorów nie ulega zmianie (dla zmiennych o automaycznym czasie życia). Destruktor sptrA wykonuje się przed destruktorem sptrB, ale ponieważ licznik referencji (refcount) w tym momencie wynosi 2, obiekt typu A, na który wskazuje sptrA nie jest niszczony. Jest niszczony dopiero gdy znika ostatnia referencja, która znika podczas destrukcji B (po wywołaniu ~B()).

1

int main, nie void main.

@kq wyjaśnił już dlaczego, ale żeby zobrazować:
1) Gdy ta ostatnia linia jest zakomentowana, kolejność wywołania destruktorów będzie

~shared_ptr<A>()
    ~A()
~shared_ptr<B>()
    ~B()
        ~shared_ptr<A>()

2) Gdy ostatnia linia nie będzie zakomentowana

~shared_ptr<A>()
~shared_ptr<B>()
    ~B()
        ~shared_ptr<A>()
            ~A()
0

Ok. Teraz rozumiem. Czyli na samym początku wywołuje się destruktor

~shared_ptr<A> 

i jeżeli refcount jest równy 1, destruktor samego obiektu.

Dzięki wielkie!

0

Można uniknąć tego problemu przez przechowywanie tylko jednej kopii danego shared_ptr (czyli nie wykorzystywać cechy “shared” z shared_ptr), a pozostałe trzymać jako weak_ptr.

To samo można osiągnąć przez użycie unique_ptr zamiast shared_ptr i gołego wskaźnika zamiast weak_ptr, tylko wtedy trzeba pamiętać by nie robić delete na tym gołym wskaźniku.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0