Reading — step 1 of 5
Learn
Algorithms
The <algorithm> header is the standard library's verb collection — sort, search, count, transform, accumulate — written once, working on every container via iterators. This lesson is where C++ stops feeling like C-with-classes and starts feeling like a language with batteries.
Iterators in one paragraph
Algorithms don't take containers; they take ranges: a begin/end iterator pair. v.begin() points at the first element, v.end() points one past the last (the fence, not the last post). Every container supplies them, which is exactly why one std::sort works on vectors, strings, and arrays alike. You've been using iterators since std::string(s.rbegin(), s.rend()) — now they're official.
The everyday verbs
#include <algorithm>
#include <numeric> // accumulate lives here, historically
std::vector<int> v = {5, 2, 8, 1, 9};
std::sort(v.begin(), v.end()); // 1 2 5 8 9
std::sort(v.begin(), v.end(), std::greater<int>()); // 9 8 5 2 1
*std::max_element(v.begin(), v.end()) // 9 — returns an ITERATOR, * it
*std::min_element(v.begin(), v.end()) // 1
std::accumulate(v.begin(), v.end(), 0LL) // 25 — sum, seeded with 0LL!
std::count(v.begin(), v.end(), 5) // 1
std::reverse(v.begin(), v.end());
std::find(v.begin(), v.end(), 8) // iterator, or v.end() if absent
Two details that separate working code from mysterious bugs: max_element returns an iterator (dereference with * to get the value — forgetting prints something address-shaped), and accumulate's third argument is both the starting value and the accumulator's type — seed with plain 0 and a vector of billions overflows an int mid-sum; 0LL makes the whole fold long long. That one's a legendary quiet bug.
Lambdas: your logic, inline
The _if family takes a predicate — and lambdas let you write it where it's used:
int evens = std::count_if(v.begin(), v.end(),
[](int x) { return x % 2 == 0; });
auto it = std::find_if(v.begin(), v.end(),
[](int x) { return x > 100; });
std::sort(people.begin(), people.end(),
[](const Person& a, const Person& b) { return a.age < b.age; });
Anatomy: [capture](params) { body }. Empty [] means the lambda uses only its parameters; [&] lets it read/write surrounding variables (a running total, say). The sort-with-comparator is the form you'll use most in real life — custom orderings without naming a one-shot function.
Your exercise: Sum of Squares of Evens
Keep the evens, square them, sum. Two honest solutions — write both, in this order:
// 1. the loop — logic bare
long long total = 0;
for (int x : v)
if (x % 2 == 0) total += 1LL * x * x; // 1LL* : widen BEFORE multiplying
// 2. algorithms — accumulate with a lambda
long long total = std::accumulate(v.begin(), v.end(), 0LL,
[](long long acc, int x) {
return x % 2 == 0 ? acc + 1LL * x * x : acc;
});
Both carry the same buried test: squares overflow int fast (46,341² already), so widen before multiplying — 1LL * x * x promotes the whole product. Empty-input edge: both forms naturally yield 0, the right answer, free. The loop is clearer today; the accumulate form is what you'll read in codebases — after this exercise, you can do both, which was the plan all along.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…