Arrays & Vectors
C++ inherits C's fixed-size array, and it comes with the same limitation: once you declare its size, it can never grow. The standard library's std::vector fixes that — it's an array that resizes itself as you add and remove elements — and in real C++ code, it's what you reach for almost every time.
A C-style array
The syntax is identical to C: a type, a name, and a size in square brackets:
#include <iostream> int main() { int scores[4] = {88, 92, 79, 95}; for (int i = 0; i < 4; i++) { std::cout << "scores[" << i << "] = " << scores[i] << std::endl; } return 0; }
scores[0] = 88 scores[1] = 92 scores[2] = 79 scores[3] = 95
That works, but scores can never hold more than 4 elements, and like in C, C++ won't stop you from reading or writing past the end of it — scores[10] compiles and silently touches memory it has no business touching.
std::vector: an array that grows
std::vector lives in the <vector> header. You create one, and .push_back() appends a new element, resizing automatically as needed:
#include <iostream> #include <vector> int main() { std::vector<int> scores = {88, 92, 79}; scores.push_back(95); scores.push_back(100); std::cout << "Count: " << scores.size() << std::endl; std::cout << "First: " << scores[0] << std::endl; std::cout << "Last: " << scores[scores.size() - 1] << std::endl; return 0; }
Count: 5 First: 88 Last: 100
scores started with 3 elements, and each push_back() call grew it — no size to declare up front, no risk of running out of room. .size() always reports the current element count, so scores[scores.size() - 1] is a reliable way to reach the last element regardless of how many push_back() calls happened before it.
Iterating with range-based for
Vectors work naturally with the range-based for loop from the previous lesson:
#include <iostream> #include <vector> int main() { std::vector<std::string> fruits = {"apple", "banana", "cherry"}; for (const std::string& fruit : fruits) { std::cout << "- " << fruit << std::endl; } return 0; }
- apple - banana - cherry
const std::string& fruit gives each loop iteration a reference to the element instead of a fresh copy of it — for a vector of strings or other larger objects, copying every element on every iteration would be wasteful, and const makes clear the loop won't modify the original vector.
std::vector does not check bounds on [] access by default — scores[100] on a 5-element vector is undefined behavior, not a helpful error. If you want a bounds-checked access that throws an exception on an invalid index, use .at() instead, e.g. scores.at(100).