C++ Arrays and Vectors
Store sequences with std::array and std::vector, choose a container from size requirements, and access elements without confusing size with a valid index.
Before this lesson
Choose between std array and std vector
Add access and traverse vector elements safely
Explain size capacity and reallocation at a practical level
The short answer
Prefer std::array for a fixed element count known at compile time and std::vector for a resizable owned sequence. Both manage storage, expose size, and work with range-based loops and standard algorithms.
Containers replace scattered variables
Separate variables such as score1, score2, and score3 duplicate every operation and fail when another score arrives. A container stores related values under one name and exposes a common traversal interface.
The container choice describes constraints. A fixed count and a runtime-growing sequence are different requirements. Use the standard container that owns those rules rather than manually managing a memory block.
| Need | Container | Key property |
|---|---|---|
| Fixed compile-time count | std::array<T, N> | Count is part of the type |
| Resizable sequence | std::vector<T> | Contiguous owned storage |
| Text characters | std::string | Text-oriented sequence operations |
| Unique key lookup | Associative container | Introduced through the capstone as needed |
Array has a fixed count
std::array<int, 3> stores exactly three integers. It can be copied as a value, reports its size, and supports range-based loops. Unlike a built-in array, it behaves consistently with the standard container model.
The size is known in the type, so arrays with different counts have different types. Use it when that fixed count is a real invariant rather than an estimate that may change.
#include <array>
#include <iostream>
int main()
{
std::array<int, 4> quarters{18, 24, 21, 30};
int total{};
for (int amount : quarters) total += amount;
std::cout << "Annual total: " << total << '\n';
}Vector owns a resizable sequence
std::vector<int> values; begins empty. push_back appends an element, size reports the current element count, and empty states whether an element can be read. Removing or inserting elements changes positions after the operation.
Capacity is allocated storage available before another reallocation. It is an implementation concern that matters for performance and iterator validity, not a count of usable elements. Start with correctness; reserve only when a realistic expected count is known.
Access requires a valid position
operator[] assumes the index is valid. at checks and throws on an invalid position. Use range-based loops when no index is required and validate externally supplied positions before access.
References and iterators into a vector can become invalid after operations that reallocate or erase elements. Do not keep one across a push_back unless the validity guarantee is understood. Reacquire it after mutation when practical.
Quick knowledge check
Answer before you reveal.
01Is values[values.size()] a valid last element?
No. Valid zero-based positions end at size minus one when nonempty.
02Does reserve change a vector's size?
No. It may allocate capacity for future elements, but it does not create elements and does not make new indexes valid.
Exercise
Practice challenge
Read positive scores into a vector until -1, then print the count, total, average, minimum, and maximum without assuming at least one score.
Requirements
- The sentinel is not stored
- Empty input has a deliberate result
- Every access stays inside the vector range
Optional extension: Reserve expected capacity and explain what it changes and what it does not.
Open in C++ compilerLesson checkpoint
One small step locks it in
Mark this lesson complete, then keep the momentum going.
Clear up the details
Frequently asked questions
Why prefer vector over a raw dynamic array?
Vector owns its allocation, cleans it automatically, tracks size, supports copying and moving, and integrates with algorithms.
When is std array useful?
When the element count is part of the type and fixed at compile time, such as twelve month totals or a small lookup table.
What happens when vector grows?
It may allocate a larger block and move or copy elements, invalidating pointers, references, and iterators into the old storage.