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 № 1Tablica 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[]
.