Czytając książkę C ++ Primer natrafiłem na następujące stwierdzenie: „Liczba elementów w tablicy jest częścią typu tablicy”. Więc chciałem dowiedzieć się, używając następującego kodu:
#include<iostream>
int main()
{
char Array1[]{'H', 'e', 'l', 'p'};
char Array2[]{'P', 'l', 'e', 'a', 's', 'e'};
std::cout<<typeid(Array1).name()<<std::endl; //prints A4_c
std::cout<<typeid(Array2).name()<<std::endl; //prints A6_c
return 0;
}
Co ciekawe, wynik pisma na dwóch tablicach pokazał, że są one jakoś inne.
- Co dzieje się za kulisami?
- Dlaczego konieczne jest, aby tablice miały typ uwzględniający ich rozmiar? Czy tylko dlatego, że jego rozmiar nie powinien się zmienić?
- Jak wpłynie to na porównywanie tablic?
Po prostu chcę być w stanie głęboko zrozumieć tę koncepcję.
Odpowiedzi:
Niealokowany dynamicznie jest z definicji kontener jednorodnych elementów o stałej wielkości . Tablica
N
elementów typuT
jest ułożona w pamięci jako ciągła sekwencjaN
obiektów typuT
.Nie sądzę, aby „typ” tablicy zawierał jej rozmiar - w rzeczywistości można użyć wskaźnika, aby odnieść się do ciągłej sekwencji
T
obiektów. Taki wskaźnik utraciłby informacje o rozmiarze tablicy.Jest to jednak przydatna rzecz. Poprawia bezpieczeństwo typu i koduje przydatne informacje w czasie kompilacji, których można używać na wiele sposobów. Na przykład można użyć odwołań do tablic w celu przeciążenia tablic o różnych rozmiarach
lub obliczyć rozmiar tablicy jako stałe wyrażenie
Naprawdę nie.
Nie możesz porównywać tablic w stylu C w taki sam sposób, w jaki porównywałbyś dwie liczby (np.
int
Obiekty). Będziesz musiał napisać jakieś porównanie leksykograficzne i zdecydować, co to znaczy dla zbiorów o różnych rozmiarach.std::vector<T>
zapewnia to i tę samą logikę można zastosować do tablic.Bonus: C ++ 11 i wyżej zapewnia
std::array
, że jest opakowaniem wokół tablicy w stylu C z interfejsem podobnym do kontenera. Powinien być preferowany niż tablice w stylu C, ponieważ jest bardziej spójny z innymi kontenerami (np.std::vector<T>
), A także obsługuje porównania leksykograficzne po wyjęciu z pudełka.źródło
std::equal
(przezstd::begin
istd::end
które są zdefiniowane dla tablic). W takim przypadku tablice o różnych rozmiarach nie są równe.Ilość miejsca przydzielanego do obiektu podczas jego tworzenia zależy całkowicie od jego typu. Alokacja, o której mówię, nie jest alokacją od
new
lubmalloc
, ale alokowaną przestrzenią, abyś mógł uruchomić konstruktor i zainicjować obiekt.Jeśli masz strukturę zdefiniowaną jako (na przykład)
Następnie podczas konstruowania obiektu:
Możesz myśleć o procesie konstruowania obiektu jako o procesie:
'a'
i'b'
do obiektu)Należy zauważyć, że 2 bajty potrzebnej przestrzeni są całkowicie zależne od typu obiektu, argumenty funkcji nie mają znaczenia. Tak więc dla tablicy proces jest taki sam, tyle że teraz potrzebna ilość miejsca zależy od liczby elementów w tablicy.
Więc typy
a
ib
muszą odzwierciedlać fakt, żea
potrzebuje wystarczającej ilości miejsca na 1 znak ib
potrzebuje wystarczającej ilości miejsca na 5 znaków. Oznacza to, że rozmiar tych tablic nie może się nagle zmienić, po utworzeniu tablicy 5-elementowej zawsze jest to tablica 5-elementowa. Aby mieć obiekty podobne do „tablicy”, których rozmiar może się różnić, potrzebujesz dynamicznej alokacji pamięci, którą w pewnym momencie powinna obejmować twoja książka.źródło
To z wewnętrznego powodu biblioteki wykonawczej. Jeśli weźmiesz pod uwagę następujące stwierdzenia, na przykład:
Wtedy staje się jasne, na czym polega problem: na przykład adresowanie
unsigned int *
musi dotyczyć samegosizeof operator
lub adresowaniaunsigned int
.Istnieje bardziej szczegółowe wyjaśnienie reszty tego, co tu widzisz, ale w dużej mierze jest to podsumowanie tego, co zostało omówione w C Programming Language, 2. wydanie autorstwa Kernighana i Ritchiego, dotyczące programu, który drukuje tekst w prostym języku zadeklarowanego typu strunowy.
źródło