Cóż, nie sądzę, że jest to naprawdę ważne, ale ponieważ program musi mimo wszystko przechowywać długość z powodu usunięcia [], dlaczego nie możemy uzyskać tych "przechowywanych informacji"?C++ dlaczego nie ma czegoś takiego jak length (array)?
Odpowiedz
Implementacja wymaga tylko przechowywania długości, i zwykle robi to tylko wtedy, gdy typ nie jest trywialnie niszczalny (tj. musi generować wywołania do destruktora) a tablica została utworzona za pomocą nowego operatora [].
Ponieważ ta właściwość typu szeregowego nie ma żadnego związku z rozmiarem tablicy, bardziej elegancka jest po prostu wywołanie długości "cookie" jako prywatnego szczegółu implementacji.
Aby uzyskać długość kompletnego obiektu tablicy (nie tylko wskaźnika), można użyć std::extent< decltype(arr) >::value
lub std::end(arr) - std::begin(arr)
.
Używanie new[]
z klasą z destruktorem to zapach kodu. Zamiast tego należy rozważyć std::vector
. Napowietrzne vs surowe new[]
(biorąc pod uwagę wszystkie bajty, które należy przydzielić, gdziekolwiek się znajdują) to jedna wartość wskaźnika, a zalety są niezliczone.
Dodaj do tego, że nie jest trudno uzyskać długość z tego, co zapewnia język, np. ze standardową implementacją szablonu. –
W rzeczywistości narzut "wektora" to dwa wskaźniki (lub rozmiary), ponieważ musi on śledzić zarówno wielkość, jak i pojemność. +1 i tak. –
@MikeSeymour Ale odejmij jeden wskaźnik narzutu, ponieważ ciasteczko "length" tablicy dynamicznej jest tak duże jak wskaźnik. – Potatoswatter
ponieważ jest to wdrożenie, w którym przechowuje te informacje. tak więc nie ma ogólnego sposobu wykonywania długości (tablica)
'length (array)' może również należeć do implementacji. – Kos
Nie wszystkie tablice są przydzielane przez new
.
void f(int* arr, size_t n)
{
length(arr); // ???
}
int main()
{
int a[5];
f(a);
}
To trywialne napisać choć, po prostu zadzwoń (std::end(arr) - std::begin(arr))
, chociaż to działa tylko dla tablic, a nie wskaźniki, które wskazują na początku tablic.
Stary trik '(sizeof (arr)/sizeof (* arr)) działa również dla prawdziwych tablic, ale podoba mi się nowy styl – stefaanv
Odejmowanie iteratora nie może być (łatwo) zoptymalizowane do stałej. sizeof jest, ale jest mniej bezpieczny. 'szablon
@JoeWreschnig, to nie są ogólne iteratory, są wskaźnikami, a różnica między dwoma adresami w tej samej tablicy może być zoptymalizowana do stałej. I zasugerowałem 'end-begin', ponieważ jest to trywialne, podczas gdy definiowanie tego szablonu funkcji nie jest trywialne, obejmuje niepoprawne parametry szablonu i brzydki deklarator tablicowy - nieodpowiedni dla początkujących! –
Rozważmy przypadek:
char* a = new char[100];
Teraz a
potrzeby do punktu do bufora, który jest co najmniej 100 znaków duży, ale system mógłby przydzielić większy bufor do wypełnienia tej.
Mając to na uwadze, widzimy, że system może natychmiast zapomnieć o rozmiarze, o jaki prosił program, o ile nadal będzie mógł zwolnić bufor odpowiednio później. (Pamiętając o wielkości przydzielonego bufora lub wykonując przydział pamięci za pomocą inteligentnej struktury danych, w której wymagany jest tylko wskaźnik do początku)
Tak więc, w ogólnym przypadku informacja, której szukasz, to nie, w rzeczywistości przechowywany w dowolnym miejscu.
Długość z pewnością nie jest przechowywana na wszystkich implementacjach. C++ pozwala na przykład na zbieranie śmieci (np. Boehmgc), a wiele kolektorów nie musi znać długości. W tradycyjnych alokatorach przechowywana długość będzie często większa niż rzeczywista długość, tj. Przydzielona długość, a nie długość.
Długość (liczba obiektów, nie bajtów) musi być gdzieś przechowywana, jeśli obiekty tablicy mają nietrywialne destruktory. Taki mechanizm jest przejrzysty dla alokatora, który ślepo przydziela niektóre bajty dopełnienia do implementacji. GC z obiektami innymi niż POD jest nową i przełomową funkcją. – Potatoswatter
tak, ale to tylko podzbiór przypadków i mogę wymyślić sposoby uniknięcia przechowywania długości (np. Kluczy wartownika). –
Nie jesteś pewien co masz na myśli. Czy chcesz używać bajtów dopełnienia dla wartownika? A co, jeśli nie ma dopełnienia? W każdym razie, wszystkie implementacje robią to w ten sam sposób, więc "nie przechowywane na wszystkich implementacjach" jest błędne ... chociaż prawdą jest również, że są przypadki, w których żadna implementacja nie przechowuje wartości długości. Zobacz moją odpowiedź. – Potatoswatter
Ale czym dokładnie jest długość tablicy? Czy jest to liczba bajtów w tablicy lub liczba elementów w tablicy?
Na przykład: w przypadku niektórych klasy A 100 rozmiar bajtów
A * myArray = Nowy A [100];
powinna długość (myArray) zwraca 100 lub 100 * 100? Ktoś może chcieć 100, ktoś może chcieć 10000.Tak więc nie ma żadnego prawdziwego argumentu.
C++ konsekwentnie faworyzuje liczenie obiektów, nie bajtów. – Potatoswatter
Rozumiem, że filozofia C++ nie ma narzucać ludziom żadnej cechy, która ma potencjalny koszt, chyba że jest nieunikniona.
Może to wiązać się z dodatkowymi kosztami przechowywania tych informacji, a użytkownik może nie chcieć ponosić tych kosztów, jeśli nie potrzebują tych informacji. A ponieważ nie ma sensu przechowywać samej długości, jeśli chcesz, nie ma powodu, aby udostępniać funkcję językową, która ma koszt dla wszystkich korzystających z tablicy.
Dla odpowiednich tablic, czyli int a[length]
, masz już takiej usługi: wystarczy zrobić
#define length(A) (sizeof(A)/sizeof(*A))
i jesteś z nim zrobić.
Jeśli chodzi o uzyskanie długości tablicy wskazywanej przez wskaźnik, dobrze, wskaźniki i tablice są dwiema różnymi koncepcjami i łączenie ich nie ma sensu, nawet jeśli odpowiednie tablice "rozpadają się" na wskaźniki, gdy są potrzebne, a ty dostęp do tablic za pomocą arytmetyki wskaźnikowej.
Ale nawet jeśli nie weźmiemy to pod uwagę i mówić o aspektach technologicznych w C++
wykonawcze nie może wiedzieć, co długość tablicy jest, ponieważ new
mogłaby polegać na malloc
, która przechowuje długość tablicy w jego specyficzne sposoby, które są rozumiane tylko przez free
: środowisko wykonawcze C++
przechowuje tylko dodatkowe informacje tylko wtedy, gdy masz niepuste destruktory. Niezły bałagan, co?
typ C++, który działa podobnie jak większość „tablic” w językach, które obsługują length(array)
jest std::vector<>
, a robi mieć std::vector<>::size()
.
Wielkość zwykły []
tablic jest znany kompilator w zakresach gdzie rozmiar jest jawne, oczywiście, ale jest możliwe, aby przekazać je do zakresów, gdzie rozmiar jest nie znany kompilator. Daje to możliwość obsługi danych tablicowych niż języki, które muszą obsługiwać interogację (ponieważ muszą zapewnić, że rozmiar jest zawsze przekazywany).
- 1. Nie ma czegoś takiego jak "język skompilowany" lub "język interpretowany"
- 2. JSON array get length
- 3. Dlaczego nie ma czegoś takiego jak IMonad <T> w nadchodzącym .NET 4.0
- 4. języki Co programowania ma czegoś takiego Haskell za `newtype`
- 5. Potrzebuję czegoś takiego jak "using Base :: *;"
- 6. Dlaczego popowa metoda Array nie ma wykrzyknika?
- 7. Dlaczego nie ma ostrzeżenia takiego jak C4738 dla podwójnego?
- 8. Postgres Array Append & Array Length for "Array Push"
- 9. Multicast - nie ma takiego urządzenia
- 10. Co sprawia, że język statycznie napisany nie ma czegoś takiego jak metoda_racjonowania Rubiego?
- 11. Nie ma wyjątku takiego elementu?
- 12. QMainWindow: Nie ma takiego pliku lub katalogu
- 13. heroku: "nie ma takiego typu jak pracownik"
- 14. Gniazdo nie zwiąże: Nie ma takiego urządzenia
- 15. nie open stream: Nie ma takiego pliku lub katalogu w
- 16. Dlaczego C nie ma literałów binarnych?
- 17. Najlepszy sposób na emulowanie czegoś takiego jak warunkowe_powrót_insetu?
- 18. Dlaczego C++ 11 nie ma szablonu typedef?
- 19. Dlaczego nie ma "static_if" w C++ 11
- 20. Możliwe jest zdefiniowanie czegoś takiego jak "między" w instrukcji if-else w C#?
- 21. Dlaczego funkcja C# nie ma funkcji zagnieżdżonych leksykalnie?
- 22. JPQL, Jak NIE wybrać czegoś
- 23. Dlaczego nie ma IntStream.flatMapToObj()?
- 24. Dlaczego nie ma kompleksowej sieci archiwów c?
- 25. Dlaczego nie ma osłony w C++ domyślnie?
- 26. śmiertelne: Nie ma takiego zdalnego kompozytora
- 27. curl.h Nie ma takiego pliku lub katalogu
- 28. jni.h: Nie ma takiego pliku lub katalogu
- 29. Char Array - dlaczego pętla nie jest nieskończona?
- 30. Dlaczego Scala nie ma decltype?
Bo tak mówi standard C++. –
To nie jest prawdziwe pytanie, czy masz kod, o który pytasz? – trumpetlicks
@trumpetlicks czemu nie? Uważam to za pytanie o funkcję językową. Przydatna może być znajomość motywacji. –