devnotes.

STL Iterators and Algorithms

Iterators provide a uniform way to traverse any STL container, and the <algorithm> header builds a huge library of generic operations on top of them.

#include <vector>
#include <algorithm>

std::vector<int> nums = {5, 2, 8, 1, 9};

std::sort(nums.begin(), nums.end());               // sorts in place: {1,2,5,8,9}

auto it = std::find(nums.begin(), nums.end(), 8);   // returns an iterator to 8
if (it != nums.end()) {
    std::cout << "Found at position " << (it - nums.begin()) << "\n";
}

int count = std::count(nums.begin(), nums.end(), 2); // how many times 2 appears

auto maxIt = std::max_element(nums.begin(), nums.end()); // iterator to the largest element

std::sort(nums.begin(), nums.end(), [](int a, int b) { // custom comparator via lambda
    return a > b;   // descending order instead of the default ascending
});

An iterator is an object that behaves like a generalized pointer — *it dereferences to get the current element, ++it advances to the next one — and every STL container exposes .begin() (the first element) and .end() (one past the last element, used as a sentinel, never dereferenced) so algorithms can work identically across vector, list, set, and more without knowing the container's internal layout.

Almost every common operation — searching, sorting, counting, transforming, accumulating — already exists as a well-tested, generic function in <algorithm> (or <numeric> for things like std::accumulate), and reaching for these instead of hand-writing loops is both less error-prone and, in idiomatic modern C++, generally the preferred style. Many algorithms accept an optional final argument — often a lambda (covered in the Modern C++ chapter) — that customizes their behavior, as with the descending-order sort above.

STL Iterators and Algorithms in C++ | DevNotes