/ / Dlaczego wywoływanie "usuń" w określony sposób na tablicy dynamicznej nie działa? - c ++, zarządzanie pamięcią, dynamiczne tablice

Dlaczego wywoływanie "usuń" w określony sposób na tablicy dynamicznej nie działa? - c ++, zarządzanie pamięcią, dynamiczne tablice

Zastanawiam się, dlaczego ten kod nie działa:

void KeyValueList::Release()
{
//(m_ppKeyValueList is a dynamic array of pointers to objects on the heap)
if (m_ppKeyValueList) {
for (int i = 0; i < m_iCapacity; ++i) {
if (m_ppKeyValueList[i]) {
delete m_ppKeyValueList[i];
}
}
/*delete[] m_ppKeyValueList;*/
for (int i = 0; i < m_iCapacity; ++i) {
delete (m_ppKeyValueList + i);
}
}
}

Dlaczego nie możemy iterować dynamicznej tablicy i delete to w ten sposób?

Odpowiedzi:

4 dla odpowiedzi № 1

Tablica dynamiczna to coś więcej niż sekwencja elementów. Zawiera również informacje o rozmiarze tablicy. Co więcej, jest po prostu jeden fragment pamięci znany programowi przydzielania. Tak samo jak w przypadku każdej pamięci dynamicznej, możesz uwolnić tylko to, co zostało przez ciebie przydzielone, a nie mniejsze podzbiory.

Dlatego język wymaga, abyś się tylko inwokował delete[] na wskaźniku uzyskanym z new[] wyrażenie, i że to jest tylko sposób na zwolnienie tej pamięci.


3 dla odpowiedzi № 2

Prosta odpowiedź:</ strong> ponieważ specyfikacje językowe mówią, że robisz to za pomocą delete[].

Lepsza odpowiedź:</ strong> ponieważ przecież dla menedżera sterty wskazana jest tablica m_ppKeyValueList jest pojedynczą dużą alokacją, nie m_iCapacity kolejne niewielkie alokacje, więc po prostu maszaby poinformować go, gdzie zaczyna się przydzielony blok, i zwolni go jako całość (po wywołaniu pojedynczych destruktorów w razie potrzeby); jeśli zachowałby każdy element jako pojedynczą oddzielną alokację na przydzielone listy bloków, byłby to głupi marnotrawstwo zasobów (i gdyby używał do tego mapy bitowej, prawdopodobnie nie miałby wystarczającej ziarnistości, aby wesprzeć ten głupi system przydziału).


0 dla odpowiedzi № 3

Bo new int[5] przydziela jeden ciągły blok na tyle duży, aby pomieścić 5 intów. new int 5 razy przydziela 5 małych bloków, z których każdy jest wystarczająco duży, aby pomieścić jedną int. Liczba dezallokacji musi być równa liczbie przydziałów.


0 dla odpowiedzi nr 4

Przypadek 1: m_ppKeyValueList jest "dynamiczna tablica wskaźników do obiektów na stercie"
W tym przypadku musisz usunąć m_ppKeyValueList kawałek po kawałku. Jeśli to masz na myśli, twoje oświadczenie będzie miało formę SomeType ** m_ppKeyValueList; Twoja alokacja i dealokacja powinny się podobać

Przydział:

m_ppKeyValueList = new SomeType*[m_iCapacity];
for (int i = 0; i < m_iCapacity; ++i) {
m_ppKeyValueList[ii] = new SomeType;
}

Dezalokacja:

for (int i = 0; i < m_iCapacity; ++i) {
delete m_ppKeyValueList[ii];
}
delete[] m_ppKeyValueList;

Jednak twój kod zawodzi, sugeruje, że nie masz "dynamicznej tablicy wskaźników do obiektów na stercie".

Przypadek 2: m_ppKeyValueList jest dynamiczną tablicą obiektów na stercie
Tutaj twoja deklaracja będzie miała formę SomeType * m_ppKeyValueList; Zamiast alokować ten kawałek po kawałku, alokacja i dealokacja przybierają znacznie prostszą formę:

Przydział:

m_ppKeyValueList = new SomeType[m_iCapacity];

Dezalokacja:

delete[] m_ppKeyValueList;

Dolna linia:
Twoje alokacje i zwolnienia muszą się zgadzać w liczbie i formie. Jeśli coś przydzielisz new musisz go zniszczyć delete. Jeśli ją przydzielisz new[] musisz go zniszczyć delete[].