Arrays and std::array
An array holds a fixed number of elements of one type, stored side by side. C++ has the built-in C-style array and its modern replacement, std::array, which knows its own size, can be copied and compared, and works with the standard algorithms.
std::array
#include <array> #include <iostream> int main() { std::array<int, 5> scores{72, 85, 90, 64, 88}; std::cout << "first " << scores[0] << ", last " << scores.back() << ", size " << scores.size() << '\n'; scores[3] = 70; int total = 0; for (int s : scores) total += s; std::cout << "average " << total / static_cast<double>(scores.size()) << '\n'; }
first 72, last 88, size 5 average 81
The size is part of the type — std::array<int, 5> — and must be a compile-time constant. Elements you don't initialise are zero when you use braces: std::array<int, 5> a{};.
Bounds checking
a[i] is fast and unchecked: an index outside the array is undefined behaviour. a.at(i) checks and throws std::out_of_range instead:
#include <array> #include <iostream> #include <stdexcept> int main() { std::array<int, 3> data{1, 2, 3}; try { std::cout << data.at(3) << '\n'; } catch (const std::out_of_range& e) { std::cout << "caught: index 3 is out of range\n"; } }
caught: index 3 is out of range
Many standard libraries can also check [] in debug builds (for example with -D_GLIBCXX_ASSERTIONS for GCC's library), which catches bugs during testing.
Arrays are values
Unlike C arrays, std::array objects can be copied, assigned, compared and returned from functions:
#include <array> #include <iostream> std::array<int, 3> reversed(std::array<int, 3> a) { return {a[2], a[1], a[0]}; } int main() { std::array<int, 3> a{1, 2, 3}; auto b = a; // a full copy b[0] = 99; std::cout << a[0] << ' ' << b[0] << '\n'; std::cout << std::boolalpha << (reversed(reversed(a)) == a) << '\n'; }
1 99 true
Algorithms work on arrays
#include <algorithm> #include <array> #include <iostream> #include <numeric> int main() { std::array<int, 6> v{4, 17, -3, 8, 17, 2}; std::sort(v.begin(), v.end()); for (int x : v) std::cout << x << ' '; std::cout << "\nsum " << std::accumulate(v.begin(), v.end(), 0) << ", max " << *std::max_element(v.begin(), v.end()) << ", count of 17: " << std::count(v.begin(), v.end(), 17) << '\n'; }
-3 2 4 8 17 17 sum 45, max 17, count of 17: 2
Lesson 25 covers the algorithms library properly.
2D arrays
#include <array> #include <iostream> int main() { std::array<std::array<char, 3>, 3> board{{ {'X', 'O', '.'}, {'.', 'X', 'O'}, {'.', '.', 'X'}, }}; for (const auto& row : board) { for (char cell : row) std::cout << cell << ' '; std::cout << '\n'; } }
X O . . X O . . X
C-style arrays
You'll meet built-in arrays in older code and C libraries. They work, but they don't know their size once passed to a function (they decay to a pointer), can't be assigned, and don't check bounds:
#include <iostream> #include <iterator> int main() { int primes[] = {2, 3, 5, 7, 11}; std::cout << std::size(primes) << " primes, last " << primes[std::size(primes) - 1] << '\n'; }
5 primes, last 11
std::size works on both kinds of array. In new code, prefer std::array for fixed sizes and std::vector (next lesson) when the size can change.
Try it yourself
Count how often each die face appears using a std::array of counters.
1: ## 2: # 3: #### 4: # 5: # 6: ###