An array stores same-type elements contiguously and addresses them with zero-based indexes. A raw array has a compile-time extent that is easily lost when passed to a function; std::array preserves fixed-size container behavior, while std::vector owns a dynamically sized contiguous buffer.
After this lesson you can choose a fixed or dynamic container, avoid one-past-the-end access, explain vector reallocation, traverse a grid, and build a prefix-sum table for repeated range totals.
The [] operator is fast but does not check bounds. vector::at checks bounds and throws an exception when the index is invalid. Beginners can use at while learning; experienced code often uses tests and invariants to keep [] safe.
Arrays can represent matrices, boards, tables, and images. In modern C++, vector<vector<int>> is flexible, while fixed arrays or flat vectors can be faster for known dimensions.
Prefix sums preprocess an array so repeated range-sum queries become fast. This pattern turns O(n) per query into O(1) per query after O(n) setup.
Compile each example, test empty and one-element inputs, and inspect how the chosen container reports its size.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> prices = {100, 250, 80};
for (int& price : prices) {
price += 10;
}
for (int price : prices) {
cout << price << ' ';
}
}
#include <iostream>
#include <vector>
using namespace std;
int maxValue(const vector<int>& values) {
int best = values[0];
for (int value : values) {
if (value > best) best = value;
}
return best;
}
int main() {
vector<int> marks = {71, 95, 84};
cout << maxValue(marks) << '\n';
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {2, 4, 6, 8};
vector<int> prefix(nums.size() + 1, 0);
for (int i = 0; i < (int)nums.size(); i++) {
prefix[i + 1] = prefix[i] + nums[i];
}
int left = 1, right = 3;
cout << prefix[right + 1] - prefix[left] << '\n';
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<vector<int>> grid = {{1, 2}, {3, 4}};
for (int row = 0; row < (int)grid.size(); row++) {
for (int col = 0; col < (int)grid[row].size(); col++) {
cout << grid[row][col] << ' ';
}
}
}
Most array parameters decay to pointers, so <code>sizeof</code> inside the function measures the pointer rather than the original array. Pass a <code>std::span</code>, accept the array by reference with its size as a template parameter, or use <code>std::array</code>/<code>std::vector</code>.
When a vector outgrows its capacity, it reallocates its contiguous storage and moves the elements. Pointers, references, and iterators into the old allocation then dangle. Call <code>reserve</code> when a useful upper bound is known, or avoid retaining element addresses across operations that may change capacity.
Use <code>std::array</code> when the element count is fixed at compile time and value semantics are useful. Choose <code>std::vector</code> when the count is determined at runtime or must grow. Both are contiguous and work with standard algorithms; unlike a raw array, <code>std::array</code> also preserves its size during assignment and function calls.
Explore 500+ free tutorials across 20+ languages and frameworks.