shared_ptr free memory

shared_ptr free memory
P2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 lat
  • Postów:19
0

Witam,

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

Kopiuj
 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 ?

kq
Moderator C/C++
  • Rejestracja:prawie 12 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Szczecin
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()).


edytowany 1x, ostatnio: kq
twonek
  • Rejestracja:prawie 11 lat
  • Ostatnio:prawie 2 lata
  • Postów:2500
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
Kopiuj
~shared_ptr<A>()
    ~A()
~shared_ptr<B>()
    ~B()
        ~shared_ptr<A>()
  1. Gdy ostatnia linia nie będzie zakomentowana
Kopiuj
~shared_ptr<A>()
~shared_ptr<B>()
    ~B()
        ~shared_ptr<A>()
            ~A()
edytowany 2x, ostatnio: twonek
P2
  • Rejestracja:ponad 8 lat
  • Ostatnio:około 7 lat
  • Postów:19
0

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

Kopiuj
~shared_ptr<A> 

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

Dzięki wielkie!

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 6 godzin
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.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.