The C++ STL Explained
The Standard Template Library (STL) is the collection of ready-made data structures and algorithms that ships with C++. It is built from three cooperating pieces: containers that hold your data, iterators that walk over it, and algorithms that operate on it through those iterators. Together they let you write std::sort(v.begin(), v.end()) instead of hand-coding a sort — less code, fewer bugs, and battle-tested performance.
Here is the big picture, then each piece.
The three pillars
- Containers store collections of objects —
std::vector(dynamic array),std::map(key-value),std::set(unique sorted values),std::list, and more. - Iterators are objects that point into a container and can move forward (and sometimes back). They are the glue between containers and algorithms.
- Algorithms are free functions like
std::sort,std::find, andstd::countthat work on a range of iterators, not on a specific container type.
Because algorithms talk to iterators rather than containers directly, one std::sort works on a vector, a deque, or an array.
Putting them together
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> marks{72, 95, 60, 88, 95};
// algorithm + iterators: sort the whole container
std::sort(marks.begin(), marks.end());
// algorithm: find a value, returns an iterator
auto it = std::find(marks.begin(), marks.end(), 88);
if (it != marks.end()) {
std::cout << "Found 88 at index "
<< (it - marks.begin()) << "\n";
}
// algorithm: count occurrences
std::cout << "95 appears "
<< std::count(marks.begin(), marks.end(), 95)
<< " times\n";
// range-based for: iterators behind the scenes
for (int m : marks) {
std::cout << m << " ";
}
std::cout << "\n";
}
Output:
Found 88 at index 3
95 appears 2 times
60 72 88 95 95
Notice the pattern: nearly every algorithm takes begin() and end() — the half-open range [begin, end) that covers the whole container.
Picking a container
| Need | Reach for |
|---|---|
| A resizable array, fast random access | std::vector |
| Key-value lookups, sorted keys | std::map |
| Key-value lookups, fastest average | std::unordered_map |
| Unique values, sorted | std::set |
| Frequent inserts at both ends | std::deque |
When in doubt, start with std::vector — it is the right default surprisingly often.
Want to learn this properly?
Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.
Browse coursesWhy prefer algorithms over hand-written loops
std::sort, std::find, and friends are correct, optimised, and express intent clearly. Reading std::any_of(...) tells the reader exactly what is happening; a raw loop makes them decode it. The modern C++ guideline is: prefer a named algorithm to a hand-rolled loop whenever one exists.
A note on ranges (C++20)
C++20 added the ranges library, which lets you call algorithms on a container directly: std::ranges::sort(marks); instead of passing two iterators. It is cleaner and harder to get wrong, and worth adopting once you understand the iterator model underneath.
Algorithms that take a function
Many of the most useful algorithms accept a small function — often a lambda — that customises what they do. This is how you sort by a custom rule or filter by a condition.
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v{5, 1, 4, 2, 3};
// sort in descending order using a lambda comparator
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// count how many values are greater than 2
auto big = std::count_if(v.begin(), v.end(), [](int x) { return x > 2; });
std::cout << "first: " << v.front() << ", big count: " << big << "\n";
}
This combination — a generic algorithm plus a tiny inline function describing your intent — is the everyday idiom of modern C++. It reads almost like a sentence: "sort these, descending"; "count those greater than two."
Common mistakes
- Mismatched iterator pairs. Passing
a.begin()andb.end()from two different containers is undefined behaviour. Always pairbegin/endfrom the same container. - Using an iterator after modifying the container. Inserting into or erasing from a
vectorcan invalidate existing iterators. Re-fetch them after changes. - Forgetting to check
end().std::findreturns the end iterator when nothing matches; dereferencing it is a bug. - Reinventing standard algorithms. Hand-writing a sort or a search is slower to write and easier to get wrong than calling the STL.
FAQ
What are the three main parts of the STL? Containers (hold data), iterators (point into and traverse data), and algorithms (operate on ranges of iterators). They are designed to plug into each other.
Is std::string part of the STL?
std::string lives in the standard library and works with STL algorithms via its iterators, though historically it is grouped with the strings library rather than the core STL containers.
Keep learning
- Templates make the STL possible — see Templates in C++.
- Start with the workhorse container in Vectors in C++.
- Then explore Maps & Sets in C++ and the C++ OOP hub.
Learn the STL hands-on with mentors in Jalgaon — join the waitlist for our C++ Programming course.
Want to learn this properly?
Join the waitlist for our courses — beginner-friendly, project-first classes in Jalgaon.
Browse coursesFounder, Infoplanet
Atul Kabra founded Infoplanet in 2001 and has spent over two decades teaching programming — C, C++, Java, databases and more — to students across Maharashtra.
Related guides
Classes & Objects in C++
Understand C++ classes and objects — defining a class, creating objects, member functions, and access control with public and private members.
Constructors & Destructors in C++
Understand C++ constructors and destructors — how objects are initialised and cleaned up, including parameterised, copy constructors, and initializer lists.
Encapsulation & Abstraction in C++
Understand encapsulation and abstraction in C++ — hiding internal data, exposing controlled interfaces, and why both make code safer and easier to change.
