Tablice są podstawową złożoną strukturą danych. Obecne są we wszystkich niemal językach programowania. Generalnie
Numerowanie elementów zawsze rozpoczyna się od zera, tzn. element pierwszy ma numer 0, a element ostatni numer (indeks) o jeden mniejszy od rozmiaru tablicy (czyli liczby elementów tablicy). Jeśli tab jest tablicą, to jej element o indeksie k jest oznaczany tab[k], a więc używamy tu nawiasów kwadratowych.
Jak zadeklarować/zdefiniować tablicę? Można to zrobić na kilka sposobów. Zajmujemy się na razie tablicami statycznymi, to znaczy, że ich rozmiar musi być znany już na etapie kompilacji programu. Tak więc deklarując tablicę musimy określić jej rozmiar. Tablice statyczne nie będące składowymi obiektów klas będą w czasie wykonania tworzone na stosie (a nie na stercie, czyli w tzw. pamięci wolnej, gdzie tworzone są obiekty). Jeśli tablica statyczna jest zadeklarowana w ciele funkcji (ogólniej: w bloku ograniczonym nawiasami klamrowymi), to jest zmienną lokalną i zostanie usunięta po wyjściu przepływu sterowania z tej funkcji.
Rozpatrzmy tablice zdefiniowane w poniższym przykładzie:
1. const int N = 20; 2. int tab1[100], 3. tab2[N], 4. tab3[] = {1,2,3,4,5}, 5. tab4[5] = {1,2}; 6. 7. int tab5[]{1,2,3,4,5}, // C++11 8. tab6[5]{1,2}, // C++11 9. tab7[5]{}; // C++11W linii drugiej powyższego przykładu zdefiniowaliśmy tablicę tab1 o 100 elementach typu int.
W linii trzeciej zdefiniowaliśmy podobną tablicę, ale o 20 elementach. Do zwymiarowania tablicy tab2 użyliśmy wartości zmiennej N i jest to prawidłowe jeśli, jak w tym przykładzie, zmienna ta zadeklarowana została z modyfikatorem const lub, jeszcze lepiej, constexpr, (C++11) i przypisana jej została wartość stała (w naszym przykładzie 20), której nie da się już zmienić. Takie stałe mogą być użyte do wymiarowania tablic, bo ich wartość jest już znana w czasie kompilacji. Natomiast nie mogą być do tego celu użyte zwykłe zmienne całkowite, a więc zadeklarowane bez modyfikatora const (większość kompilatorów dopuszcza taką konstrukcję, ale nie jest to zgodne ze standardem; program staje się zatem nieprzenośny). Takie tablice są zatem statyczne — ustalenia ich rozmiaru nie można odłożyć do etapu wykonywania programu, a więc, na przykład, uzależnić od wartości przez program wczytywanych.
Po takich deklaracjach tablice tab1 i tab2 zostały utworzone, tzn. został im przydzielony odpowiedni obszar w pamięci, ale wartości poszczególnych elementów nie zostały określone i pozostają niezainicjowane: ich wartości są z punktu widzenia programisty całkowicie przypadkowe.
Inaczej jest w przypadku tab3 i tab4. Elementy tablicy tab3 będą zainicjowana podanymi wartościami; tablica będzie miała taki rozmiar, jaki wynika z liczby elementów podanych w nawiasach klamrowych. Zauważmy, że w ogóle nie podaliśmy tu jawnie wymiaru: kompilator policzy zainicjowane elementy i dobierze rozmiar sam.
A jak będzie z tab4? Tu liczbę elementów podaliśmy: ma ich być pięć. Z drugiej strony, zainicjowaliśmy tylko dwa elementy. Otóż kompilator utworzy teraz tablicę pięcioelemenową, zainicjuje dwa pierwsze elementy podanymi liczbami, natomiast pozostałe zainicjuje zerami. Wynika z tego, że jeśli chcemy utorzyć tablicę o określonym wymiarze i od razu wypełnić ją zerami, to możemy użyć składni
int tab[100000] = {};bo podanie inicjatora klamrowego, nawet pustego, wymusza zainicjowanie wszystkich elementów zerami.
Zauważmy też, że w nowym standardzie (C++11) znaki równości przed inicjatorem klamrowym mogą być opuszczone, ja to widzimy w wtrzech ostatnich liniach przykładu.
T.R. Werner, 21 lutego 2016; 20:17