2013-08-04 12 views
5
int* arr = new int[count]; 

delete arr; 

Dlaczego to działa? Sprawdziłem i to faktycznie uwalnia pamięć. Z tego, co przeczytałem, potrzebuję delete[] arr; w przeciwnym razie nie zwolni to całej pamięci.C++ Czy usunąć pamięć tablicy bez nawiasów?

+1

AFAIK to UB. – Borgleader

+3

"Dlaczego to działa?" - nie, wydaje się, że działa. –

+0

Bez nawiasów wywołujesz tylko jeden destruktor, a nie wszystkie destruktory w tablicy. Zobacz także http://stackoverflow.com/questions/2425728/delete-vs-delete-operators-in-c- – GreatBigBore

Odpowiedz

7

Teraz spróbuj go z wypełniania tablicę ciągów po 100 bajtów każdy, i sprawdzić, czy nadal zwalnia całą przydzieloną pamięć ...

Jest niezdefiniowane zachowanie, i jak zawsze pojawi czasami UB pracować. W twoim przypadku nie masz destruktora dla obiektów w pamięci, więc nie ma "dalszej pracy", po prostu zwolnij całą pamięć [1]. Ale jeśli masz obiekt, który ma destruktor, który robi coś użytecznego, to (prawdopodobnie) nie zostanie wywołany.

Powinieneś ZAWSZE używać delete [], jeśli użyłeś new T[size]; do przydzielenia. Nie mieszaj tych dwóch, zawsze jest źle - tylko czasami to DZIAŁA, żeby działać [tak, jak NIEKTÓRE rozmiary kluczy w calach działają na nakrętki mm i odwrotnie - ale nadal nie należy używać klucza płaskiego z nakrętkami metrycznymi].

[1] Uwaga: może to działać dla tej konkretnej kombinacji biblioteki kompilatora/C++. Kompilowanie go z innym kompilatorem, używanie innej biblioteki C++ lub kompilowanie dla innego systemu operacyjnego może spowodować awarię, gdy spróbujesz tego samego.

3

usuwanie i usuwanie [] są w rzeczywistości różnymi operatorami, a użycie niewłaściwego jest zawsze błędem. Problem polega na tym, że często wydaje się to być w porządku, ale kupa została zepsuta i najprawdopodobniej wkrótce doznasz pozornie niezwiązanej z nią awarii.

+0

Nie rozumiem, dlaczego jestem oznaczony za to, ponieważ jest PRAWDA. Możesz spróbować uruchomić valgrind lub podobne narzędzie do analizy pamięci i pokaże on, kiedy wystąpi uszkodzenie sterty. –

+1

Mam nadzieję, że komentatorzy downwisów. Jestem zainteresowany, która część może nie być poprawna. – user2029077

+0

Nie wiem dlaczego - jest to całkowicie dokładna odpowiedź. – Puppy

6

Różnica nie jest to, czy przydzielona pamięć jest prawidłowo uwolnione - czy używasz

delete 

lub

delete[] 

pamięć nadal będzie prawidłowo zwalniane.

Różnica polega na tym, czy destruktory będą prawidłowo wywoływane.

delete // will only invoke the destructor of the first element of the array. 

delete[] // will invoke the destructor for *each* element of the array. 

ta nie ma praktycznego wpływu na prymitywnych typów, takich jak int lub float, ale gdy masz tablicę pewnej klasy, różnica może być krytyczny.

+0

Mogę sobie wyobrazić implementację, w której to byłoby prawdą. Czy masz rzeczywistą dokumentację implementacji, która pokazuje, że jest to prawda? – sehe

+2

Brak dokumentów, tylko moje własne doświadczenie w tym jest z Visual C++. Trochę za długo, ale pamiętam, że mam do czynienia z błędami, ponieważ błędnie użyłem delete zamiast delete []. Jestem pewien, że zachowywał się tak, jak to opisałem ... pamiętaj, że * x usuwa to samo położenie co x [0] i deklaruje x jako wskaźnik do tego, co nie mówi nic o tym, czy obiekt docelowy jest skalarem czy tablicą, więc operator usuwający nie będzie wiedział, że musi zniszczyć tablicę obiektu względem obiektu skalarnego, chyba że powiesz to za pomocą odpowiedniego konstruktu delete. – Zenilogix

Powiązane problemy