std::array in C++
If you’ve used plain C-style arrays in C++, you’ve probably hit their annoying limits: they forget their own size, they can’t be copied with =, and they silently decay into pointers the moment you pass them to a function. std::array fixes all of that while staying just as fast.
What Is std::array?
std::array is a fixed-size container from the C++ Standard Library, added in C++11. It wraps a normal array in a proper object so it knows its own length, works with STL algorithms, and can be copied and returned like any other value — all with zero runtime cost. It lives in the <array> header.
#include <array>
#include <iostream>
int main() {
std::array<int, 5> scores = {90, 85, 70, 100, 60};
std::cout << "First score: " << scores[0] << "\n";
std::cout << "How many: " << scores.size() << "\n";
return 0;
}
The type is std::array<ElementType, Count>. Here it’s an array of 5 ints. That 5 is part of the type — the size is fixed at compile time and can never change.
Declaring a std::array
You can initialize a std::array a few different ways:
#include <array>
int main() {
std::array<int, 3> a = {1, 2, 3}; // full list
std::array<int, 3> b = {1}; // {1, 0, 0} — rest are zero
std::array<int, 3> c = {}; // {0, 0, 0} — all zero
std::array<double, 2> d{3.14, 2.7}; // brace init, no =
return 0;
}
Notice that if you supply fewer values than the size, the remaining elements are value-initialized to zero. That’s safer than a C-style array, whose uninitialized elements contain garbage.
Why std::array Knows Its Own Size
This is the headline feature. A C-style array can’t reliably tell you how many elements it holds once you pass it anywhere. A std::array always can, because the length is baked into its type:
#include <array>
#include <iostream>
int main() {
std::array<int, 4> nums = {10, 20, 30, 40};
std::cout << "Elements: " << nums.size() << "\n"; // 4, always correct
return 0;
}
This matters because it kills a whole class of bugs. You never have to pass a separate “length” variable around and hope it stays in sync with the array.
Looping Over a std::array
Because std::array knows its size, the clean range-based for loop just works:
#include <array>
#include <iostream>
int main() {
std::array<int, 5> scores = {90, 85, 70, 100, 60};
for (int s : scores) {
std::cout << s << " ";
}
std::cout << "\n";
return 0;
}
If you need the index too, a classic loop with .size() is safe here — no risk of getting the length wrong:
for (std::size_t i = 0; i < scores.size(); ++i) {
std::cout << "scores[" << i << "] = " << scores[i] << "\n";
}
Passing std::array to a Function
A C-style array decays to a pointer when passed to a function, losing its size. A std::array does not — you pass it as a whole object, usually by const reference to avoid copying:
#include <array>
#include <iostream>
double average(const std::array<int, 5>& data) {
int total = 0;
for (int x : data) total += x;
return static_cast<double>(total) / data.size(); // size still known!
}
int main() {
std::array<int, 5> scores = {90, 85, 70, 100, 60};
std::cout << "Average: " << average(scores) << "\n";
return 0;
}
The function can call data.size() because the length travels with the object. This is efficient because const& avoids copying the array while still giving read access.
Bounds Checking with .at()
Like std::vector, std::array offers .at(), which checks the index and throws std::out_of_range if you go too far. Plain [] does not check and is undefined behavior out of bounds:
std::array<int, 3> a = {1, 2, 3};
int x = a[5]; // undefined behavior — silent bug
int y = a.at(5); // throws std::out_of_range — a clear, catchable error
Use [] in tight loops where you know the index is valid, and .at() when an index might be wrong and you want a real error instead of corruption.
std::array vs C-Style Array vs std::vector
| Feature | C-style array | std::array | std::vector |
|---|---|---|---|
| Size fixed at compile time | yes | yes | no |
Knows its own .size() | no | yes | yes |
| Can grow/shrink | no | no | yes |
Bounds-checked .at() | no | yes | yes |
| Decays to pointer | yes | no | no |
| Lives on | stack | stack | heap |
The rule of thumb: reach for std::array when the size is known and constant, std::vector when it changes, and avoid raw C-style arrays in new code.
Related Articles
- C++ Arrays Tutorial — the C-style arrays std::array improves on
- C++ Array vs Vector — when fixed size beats dynamic size
- C++ Vector Tutorial — the resizable cousin of std::array
- How to Find the Size of an Array in C++ — the problem std::array solves cleanly
- How to Pass an Array to a Function in C++ — pointer decay explained
Take Your C++ Further
If you’re looking to go deeper with C++, the C++ Better Explained Ebook is perfect for you — whether you’re a complete beginner or looking to solidify your understanding. Just $19.