C++ Iterators and Standard Algorithms
Express search, count, sort, transformation, and accumulation with iterator ranges and standard algorithms while keeping mutation and complexity visible.
Before this lesson
Explain a half-open iterator range
Use find count_if sort transform and accumulate
Recognize iterator invalidation and mutation
The short answer
Iterators describe positions in a sequence, and a half-open begin-to-end range lets standard algorithms work across many containers. Prefer a named algorithm when it states the operation more directly than a hand-written loop.
Iterators generalize positions
An iterator refers to a position in a sequence. begin() refers to the first element and end() to the sentinel after the last. Algorithms use the half-open range [begin, end), which naturally represents empty sequences and adjoining subranges.
Iterators have capabilities. Vector iterators support random access; other containers may support only forward movement. Choose algorithms whose requirements match the range rather than assuming every iterator behaves like an index.
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
std::vector<int> values{8, 3, 12, 3};
auto found = std::find(values.begin(), values.end(), 12);
if (found != values.end())
{
std::cout << "Found: " << *found << '\n';
}
}Algorithms name common operations
std::find searches for a value, std::count_if counts predicate matches, std::sort reorders a range, std::transform maps values, and std::accumulate folds a range into a result. Their names make intent searchable and their contracts have known complexity.
Check return contracts. A failed find returns the supplied end iterator, which must not be dereferenced. Sorting mutates the range; copy first when original order is part of the requirement.
| Goal | Algorithm | Important effect |
|---|---|---|
| Find equal value | std::find | Returns end when absent |
| Count matches | std::count_if | Does not mutate elements |
| Order values | std::sort | Mutates the range |
| Map values | std::transform | Writes to an output range |
| Combine values | std::accumulate | Initial value controls result type |
Lambdas supply local behavior
A lambda creates a callable object near the use site. Parameters describe each element, the body computes the decision or result, and captures provide surrounding context. [threshold] copies one value; [&threshold] borrows it and requires the original to remain alive.
Keep a lambda focused. When behavior has a domain name, substantial branches, or reuse, move it into a named function or function object. Local syntax should not hide an important policy.
Mutation and cost remain real
Algorithms do not make costs disappear. Sorting is generally O(n log n), searching an unsorted vector is linear, and transformation writes a result. Repeatedly sorting inside a loop is still expensive even when each call is concise.
Container mutations can invalidate iterators. Do not erase or append casually while an algorithm or loop holds positions into the same vector. Use erase-remove patterns or newer range-aware facilities only after understanding the underlying ownership and validity.
Quick knowledge check
Answer before you reveal.
01Why does end not refer to the last element?
It is the one-past-the-end sentinel, making an empty range begin equal end and allowing consistent half-open ranges.
02Does std sort return a sorted copy?
No. It rearranges the supplied range in place.
Exercise
Practice challenge
Given a vector of temperatures, count readings above a threshold, sort a copy, and calculate the sum with standard algorithms.
Requirements
- The original sequence remains unchanged
- The predicate captures the threshold clearly
- Empty input produces a valid count and sum
Optional extension: Transform Celsius values into Fahrenheit values in a new vector.
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
Do algorithms replace every loop?
No. Use them when their name and contract express the operation clearly; a direct loop may better model complex stateful behavior.
What does a lambda capture?
It makes selected surrounding values or references available inside the callable object. The capture mode affects lifetime and mutation.
Why include numeric for accumulate?
Standard algorithms are grouped across headers; accumulation lives in numeric.