2010-03-09 11 views
18

Po przydzieleniu tablicy przy użyciu new [], dlaczego nie można dowiedzieć się rozmiar tej tablicy od wskaźnika? Musi być znany w czasie wykonywania, w przeciwnym razie delete [] nie będzie wiedział, ile pamięci można zwolnić.Dlaczego nie ma dostępu do rozmiaru nowej tablicy [] 'd?

O ile czegoś nie brakuje?

+0

Prosty dobry projekt nie musi wiedzieć - w skomplikowanym przypadku trzeba samemu dużo zarządzać. Istnieją ogólne funkcje debugowania dla kompilatora, które powiedzą ci - ale jeśli tego potrzebujesz, prawdopodobnie Twój projekt jest nieprawidłowy. –

+0

Często zastanawiałem się, dlaczego nigdy nie widzisz alokatora, który nie zna rozmiaru i wymaga, aby został przekazany podczas usuwania. ponieważ jak często zdarzyło Ci się usunąć blok pamięci i nie byłeś w stanie łatwo obliczyć jego rozmiaru? Wydaje mi się, że nigdy nie było tak naprawdę korzyści z wdrożenia systemu z tym ograniczeniem ... – matt

+0

Prawdopodobnie nakładałoby to niepotrzebne ograniczenia na wdrożenie tak niskiego poziomu operacji. Po tym wszystkim wiesz, ile prosiłeś o przydzielenie tablicy, więc nie ma pilnej potrzeby środowiska wykonawczego, aby móc ci to powiedzieć. – UncleBens

Odpowiedz

14

W typowej implementacji rozmiar dynamicznego bloku pamięci jest w jakiś sposób przechowywany w samym bloku - to prawda. Ale nie ma standardowego sposobu dostępu do tych informacji. (Wdrożenia mogą dostarczyć konkretnych sposobów implementacji). Tak właśnie jest z malloc/free, tak to jest z new[]/delete[].

W rzeczywistości, w typowej implementacji alokacje pamięci surowy dla new[]/delete[] połączeń są ostatecznie przetwarzane przez jakiś realizacji specyficznych malloc/free -jak pary, co oznacza, że ​​delete[] naprawdę nie musisz się martwić o ile pamięci do zwalnianie: to po prostu nazywa to wewnętrznym free (lub czymkolwiek on się nazywa), który się tym zajmuje.

Co trzeba wiedzieć, to ile elementów do destruct w sytuacjach, gdy typ elementu tablicy ma nietrywialny destruktor. I na tym właśnie polega twoje pytanie - liczba elementów tablicy, a nie rozmiar bloku (te dwa nie są takie same, blok może być większy niż naprawdę wymagany dla samej tablicy). Z tego powodu liczba elementów w tablicy jest zwykle również przechowywana wewnątrz bloku przez new[], a następnie pobierana przez delete[] w celu przeprowadzenia prawidłowego zniszczenia elementu tablicy. Nie ma również standardowych sposobów dostępu do tego numeru.

(oznacza to, że w przypadku ogólnym, typowy blok pamięci przydzielone przez new[] się niezależnie od siebie, jednocześnie przechowywanie zarówno fizyczny rozmiar bloku bajtów i licznik operacji elementu tablicy. Wartości te są przechowywane w różnych poziomach C++ mechanizm alokacji pamięci - alokator pamięci surowej i odpowiednio new[] - i nie współdziałają ze sobą w żaden sposób).

Należy jednak zauważyć, że z powyższych powodów liczba elementów tablicy jest normalnie przechowywana tylko wtedy, gdy typ elementu tablicy ma nietrywialny destruktor. To znaczy. ten licznik nie zawsze jest obecny. Jest to jeden z powodów, dla których zapewnienie standardowego sposobu dostępu do tych danych jest niewykonalne: trzeba albo przechowywać je zawsze (co marnuje pamięć), albo ograniczać jego dostępność przez typ destruktora (co jest mylące).

celu zilustrowania powyższego, gdy tworzysz tablicę int s

int *array = new int[100]; 

rozmiaru tablicy (czyli 100) jest nie normalnie przechowywane przez new[] od delete[] nie dba o niego (int nie ma destruktora). Fizyczny rozmiar bloku w bajtach (np. 400 bajtów lub więcej) jest normalnie przechowywany w bloku przez podzielnik pamięci surowej (i używany przez deallocator pamięci surowej wywoływany przez delete[]), ale dla niektórych może się łatwo okazać 420 przyczyna związana z wdrożeniem. Tak więc ten rozmiar jest w zasadzie bezużyteczny, ponieważ nie będzie można wyprowadzić z niego dokładnego oryginalnego rozmiaru tablicy.

+1

Tak, alokator pamięci może nie znać rozmiaru tablicy. Może zwrócił blok następnego największego dostępnego rozmiaru i nie obchodzi nawet, że użyłeś tylko 75% to. –

7

Najprawdopodobniej masz do niego dostęp, ale wymagałoby to dokładnej znajomości twojego przydziału i nie byłoby przenośne. Standard C++ nie określa, w jaki sposób implementacje przechowują te dane, więc nie ma spójnej metody ich uzyskiwania. Uważam, że nie zostało to jeszcze określone, ponieważ różne alokatory mogą chcieć przechowywać je na różne sposoby w celu zwiększenia wydajności.

+0

Wciąż byłoby fajnie, gdyby standard określił operator 'len (...)', więc można uzyskać rozmiar tablicy za pomocą tego operatora (i autorzy mogą zaimplementować tego operatora, tak jak chcą). .. :( – smerlin

+4

@smelin Czy to nie to, do czego służy 'std :: vector <>'? – KitsuneYMG

5

Ma to sens, ponieważ na przykład rozmiar przydzielonego bloku niekoniecznie musi być taki sam, jak rozmiar tablicy. Podczas gdy it is true, że new[] może przechowywać liczbę elementów (wywoływanie każdego destruktora elementów), nie musi tak, jak nie byłoby to wymagane dla pustego destruktora. Nie ma również standardowej metody (C++ FAQ Lite 1, C++ FAQ Lite 2) implementacji, w której new[] przechowuje długość tablicy, ponieważ każda metoda ma swoje wady i zalety.

Innymi słowy, pozwala alokacji na tak szybkie i tanie, jak to możliwe, nie określając niczego na temat realizacji. (Jeśli implementacja musi przechowywać rozmiar tablicy, a także rozmiar przydzielonego bloku za każdym razem, marnuje pamięć, której możesz nie potrzebować).

3

Krótko mówiąc, standard C++ nie wymaga wsparcia. Możliwe, że jeśli wiesz wystarczająco dużo o wewnętrznych cechach twojego kompilatora, możesz dowiedzieć się, jak uzyskać dostęp do tych informacji, ale to ogólnie być uważane za złą praktykę. Zwróć uwagę, że może istnieć różnica w układzie pamięci dla tablic alokowanych w sterty i tablic alokowanych w stos.

Pamiętaj, że w zasadzie to, o czym tu mówisz, to tablice w stylu C - nawet jeśli new i delete są operatorami C++ - a zachowanie jest dziedziczone po C. Jeśli chcesz mieć tablicę C++, która jest size, powinieneś używać STL (np. std :: vector, std :: deque).

+0

Tak, generalnie nie używam tablic w stylu C - to było po prostu ogólne pytanie (jeśli to było możliwe) w niektórych przypadkach zapisuje pewną ilość pamięci –