Od wersji standardu C++11 istnieje w bibliotece standardowej specjalny typ danych std::array (z nagłówka array). Właściwie, jak się przekonamy, jest to tzw. szablon klasy. Na razie wystarczy nam wiedzieć, że zamiast tworzyć „normalne” tablice w stylu C, możemy tworzyć obiekty klasy array<Typ,size>, gdzie Typ jest typem elementów tablicy, a size jest jej wymiarem. W dalszym ciągu podany wymiar musi być stałą kompilacji. Zmiennej tego typu można używać tak jak tablicy, poprzez indeksowanie. Również inicjowanie wygląda podobnie jak dla zwykłych tablic; na przykład
1. #include <iostream> 2. #include <array> 3. int main() { 4. std::array<double,5> a1; 5. std::array<int,3> a2{1,2,3}; 6. for (int i = 0; i < 5; ++i) a1[i] = i+0.5; 7. for (int i = 0; i < 5; ++i) std::cout << a1[i] << " "; 8. std::cout << std::endl; 9. for (int i = 0; i < 3; ++i) std::cout << a2[i] << " "; 10. std::cout << std::endl; 11. }drukuje
0.5 1.5 2.5 3.5 4.5 1 2 3Tablice tego typu mają jednak szereg zalet w stosunku do zwykłych tablic. Przede wszystkim są obiektami i „znają” swój wymiar, również wtedy, kiedy zostaną wysłane do funkcji jako argument. Można ten wymiar uzyskać poprzez wywołanie metody na rzecz takiego obiektu: arr.size() (linia ➊ w przykładzie poniżej), albo poprzez wywołanie bibliotecznej funkcji: std::size(arr) (linia ➌), gdzie arr jest taką tablicą. Jak widzimy w przykładzie, to będzie działać również dla tablicy przesłanej do funkcji (w tym przypadku funkcji printArray). Do poszczególnych elementów można się odwoływać poprzez indeks, jak to już widzieliśmy, albo poprzez metodę: arr.at() (linia ➍):
1. #include <array> 2. #include <cstddef> // size t 3. #include <iostream> 4. #include <string> 5. using std::array; using std::cout; 6. 7. void printArray(const array<int,8>& a) { 8. cout << "Version <int,EIGHT>: " 9. << "a.size() = " << a.size() << "\n"; ➊ 10. for (const auto& e : a) cout << e << " "; ➋ 11. cout << "\n"; 12. } 13. 14. template <typename E, std::size_t SIZE> 15. void printArray(const array<E,SIZE>& a) { 16. cout << "Template version: " 17. << "std::size(a) = " << std::size(a) << "\n"; ➌ 18. for (std::size_t i = 0; i < a.size(); ++i) 19. cout << a.at(i) << " "; ➍ 20. cout << "\n"; 21. } 22. 23. int main() { 24. array<int,8> ai{1,2,3,4,5}; 25. for (auto& e : ai) ++e; ➎ 26. printArray(ai); 27. 28. array<std::string,5> as{"K","L","M","D"}; 29. for (auto& e : as) e += "!"; 30. printArray(as); 31. }
Przykład ilustruje też kilka elementów, których jeszcze nie znamy. Forma pętli (na przykład w liniach ➋ i ➎) jest charakterystyczna dla kolekcji z biblioteki standardowej — omówimy ją w rozdziale o pętlach . Z kolei druga forma funkcji printArray jest tak naprawdę szablonem — dzięki temu może działać dla tablic o różnych typach elementów i o różnych rozmiarach. Więcej o tym w rozdziale o szablonach .
Program drukuje
Version <int,EIGHT>: a.size() = 8 2 3 4 5 6 1 1 1 Template version: std::size(a) = 5 K! L! M! D! !Może się zdarzyć, że tablicę typu std::array chcemy wysłać do funkcji, która oczekuje zwykłej tablicy (czyli właściwie wskaźnika). Można to łatwo zrobić poprzez wywołanie arr.data(), które zwraca te same dane jako wskaźnik do „zwykłej” C-tablicy.
T.R. Werner, 23 lutego 2022; 19:40