C++ fundamentals
C++ std::vector for beginners
A std::vector stores a sequence of values that can grow while your program runs. It is a standard library container, so it manages its own memory as you append items. A vector is useful when the number of values comes from input or changes over time. A fixed-size array is a better fit when the size is known and never changes.
Create and grow a vector
Include <vector> before declaring a vector. Write its element type inside angle brackets, then give the variable a name. For example, std::vector<int> scores; creates an empty vector of integers. The std:: prefix names the standard library namespace and makes the origin of the type clear.
Use push_back(value) to append one value to the end. The vector adjusts its storage when needed, so you do not choose a maximum capacity in the declaration. size() reports how many elements currently exist. It does not report how much storage the vector has reserved internally.
You can also initialize a vector with values between braces. The elements keep their insertion order. Repeatedly appending to the end preserves earlier values and gives the new value the next index. The first element has index zero, so a vector with four elements has indices 0 through 3.
Append values
#include <iostream>
#include <vector>
int main() {
std::vector<int> readings;
readings.push_back(6);
readings.push_back(8);
readings.push_back(10);
readings.push_back(12);
std::cout << readings.size() << " values\n";
for (int reading : readings) {
std::cout << reading << '\n';
}
return 0;
}
Expected output:
4 values 6 8 10 12
This program starts with an empty vector and adds four readings. The range-based for loop visits each element in order. Its local variable reading receives a copy of the current integer, which is enough when the program only prints each value.
Read elements and loop
Use a range-based loop when you need every value and do not need its position. This loop avoids writing index arithmetic and adapts naturally when the vector size changes. If you need to update each stored value, declare the loop variable as a reference, such as int& reading. Without the ampersand, changing the loop variable changes only its copy.
Use indexing when the position matters. The at(index) member function checks that the index is within the vector and throws an exception when it is not. The subscript operator, written values[index], does not perform a bounds check. Use it only when your code has already proved that the index is valid.
A safe index loop compares the index with values.size() before accessing the element. The final valid index is one less than the size. Avoid computing size() - 1 for an empty vector, because an unsigned size value cannot represent a negative number. A loop using i < values.size() naturally runs zero times when there are no values.
Use an index to select matching values
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
const std::vector<int> scores{72, 91, 84, 67};
int total = 0;
for (std::size_t i = 0; i < scores.size(); ++i) {
if (scores.at(i) >= 80) {
total += scores.at(i);
}
}
std::cout << total << '\n';
return 0;
}
Expected output:
175
The index loop lets the condition inspect and select elements by position. This code adds scores that meet the threshold. It uses std::size_t, an unsigned integer type commonly used for container sizes and indices. The loop condition prevents an out-of-range access.
Common mistakes
A vector index is not automatically valid because it has an integer type. An empty vector has no valid index. Check the size or use at() when you want a runtime bounds check. When you remove elements, later indices can shift, so do not keep an index and assume it still identifies the same item.
Do not confuse size() with an index. The size counts elements; indexing begins at zero. For a vector of size five, valid indices are 0, 1, 2, 3, and 4. A loop condition using i <= values.size() runs one step too far. Use a strict less-than comparison.
Choose the element type to match the data. A vector of integers cannot store fractional values without losing information, while a vector of strings is appropriate for words. The type appears once in the declaration and applies to every element. For values that should not change, make the vector const and use read-only operations.
Vectors store elements contiguously, but appending can cause the container to allocate new storage. If you keep pointers or references to elements while appending, an allocation can invalidate them. Avoid holding such references across operations that may grow the vector unless you understand and manage that invalidation.
Exercise
Read four daily temperatures into a vector. Print how many readings are above 20. Sample input:
17 23 21 18
Expected output:
2
Show one possible solution
#include <iostream>
#include <vector>
int main() {
std::vector<int> temperatures;
for (int i = 0; i < 4; ++i) {
int temperature;
if (!(std::cin >> temperature)) {
return 1;
}
temperatures.push_back(temperature);
}
int warmDays = 0;
for (int temperature : temperatures) {
if (temperature > 20) {
++warmDays;
}
}
std::cout << warmDays << '\n';
return 0;
}
Practice C++ loops and learn input validation next.
Hint 1: Append each input value to the vector. Hint 2: Visit the stored values and increment a counter when a reading is greater than 20.
Related guides
Keep learning with CppPath
Continue with std::vector Basics. The full lesson includes a quiz and a checked coding challenge with a free account.