Chapter 15: STL (Standard Template Library)
The Standard Template Library (STL) in C++: Your Superpower Toolkit!
Hello my superstar student! π Welcome to Lesson 15 β The Standard Template Library (STL) β the most powerful and most used part of modern C++!
The STL is a collection of generic, reusable, high-performance data structures and algorithms that let you work with collections of data without writing everything from scratch.
Think of the STL as a Swiss Army knife:
- Containers β different ways to store data (like different kinds of boxes)
- Algorithms β ready-made operations you can perform on those containers (like built-in tools)
- Iterators β the way to βwalk throughβ the data in containers (like a pointer that knows how to move)
Today weβll cover everything in great detail:
- Containers: vector, list, deque, map, unordered_map, set, unordered_set
- Algorithms: sort, find, transform, accumulate
- Iterators & the beautiful range-based for loop
Letβs dive in with tons of examples you can run right away!
1. The Big Picture: STL Containers Overview
| Container | What it is | Best for | Ordered? | Random Access? | Duplicates allowed? |
|---|---|---|---|---|---|
| std::vector | Dynamic array | General purpose, fast access | Yes | Yes | Yes |
| std::list | Doubly-linked list | Frequent insert/delete in middle | Yes | No | Yes |
| std::deque | Double-ended queue | Fast insert/delete at both ends | Yes | Yes | Yes |
| std::map | Sorted key-value pairs (red-black tree) | Sorted lookup by key | Yes | No | No (keys unique) |
| std::unordered_map | Hash table key-value pairs | Fast average-case lookup | No | No | No (keys unique) |
| std::set | Sorted unique elements | Sorted collection, no duplicates | Yes | No | No |
| std::unordered_set | Hash table unique elements | Fast lookup, no duplicates | No | No | No |
Include headers:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#include <vector> #include <list> #include <deque> #include <map> #include <unordered_map> #include <set> #include <unordered_set> #include <algorithm> // for algorithms #include <numeric> // for accumulate #include <iostream> #include <string> |
2. std::vector β The Most Popular Container
Dynamic array β grows automatically, fast random access.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <vector> #include <iostream> int main() { // Create vector std::vector<int> numbers = {10, 20, 30, 40, 50}; // Add elements numbers.push_back(60); // at the end numbers.insert(numbers.begin() + 2, 25); // insert at position 2 // Access std::cout << "First: " << numbers.front() << "\n"; // 10 std::cout << "Last: " << numbers.back() << "\n"; // 60 std::cout << "Element at index 3: " << numbers[3] << "\n"; // 40 // Size & capacity std::cout << "Size: " << numbers.size() << "\n"; // 7 std::cout << "Capacity: " << numbers.capacity() << "\n"; // usually >= size // Range-based for loop (beautiful!) std::cout << "All numbers: "; for (int n : numbers) { std::cout << n << " "; } std::cout << "\n"; // Remove numbers.pop_back(); // remove last numbers.erase(numbers.begin()); // remove first return 0; } |
When to use vector: Almost always β unless you need frequent inserts/deletes in the middle.
3. std::list β Doubly-Linked List
Fast insert/delete anywhere, but no random access.
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <list> std::list<std::string> fruits = {"Apple", "Banana", "Cherry"}; fruits.push_front("Mango"); // fast at beginning fruits.push_back("Orange"); // fast at end fruits.insert(++fruits.begin(), "Kiwi"); // insert after first for (const auto& f : fruits) { std::cout << f << " "; } // Output: Mango Apple Kiwi Banana Cherry Orange |
When to use list: When you do lots of inserts/deletes in the middle.
4. std::map & std::unordered_map β Key-Value Stores
std::map β sorted by key (red-black tree) std::unordered_map β fast average lookup (hash table)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include <map> #include <unordered_map> #include <string> int main() { // Sorted map std::map<std::string, int> phoneBook; phoneBook["Alice"] = 123456; phoneBook["Bob"] = 789012; phoneBook["Charlie"] = 345678; // Automatically sorted by key! for (const auto& [name, number] : phoneBook) { std::cout << name << ": " << number << "\n"; } // Output: // Alice: 123456 // Bob: 789012 // Charlie: 345678 // Fast unordered_map std::unordered_map<std::string, std::string> capitals = { {"India", "New Delhi"}, {"France", "Paris"}, {"Japan", "Tokyo"} }; std::cout << "Capital of India: " << capitals["India"] << "\n"; // Check if exists if (capitals.find("Germany") != capitals.end()) { std::cout << "Found!\n"; } else { std::cout << "Not found\n"; } return 0; } |
When to use:
- map β when you need sorted order or range queries
- unordered_map β when you need fast lookup (O(1) average)
5. std::set & std::unordered_set β Unique Sorted/Unsorted Collections
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <set> std::set<int> uniqueNumbers = {5, 2, 8, 1, 5, 3}; // 5 appears only once // Automatically sorted! for (int n : uniqueNumbers) { std::cout << n << " "; // 1 2 3 5 8 } uniqueNumbers.insert(4); uniqueNumbers.erase(2); // Check existence if (uniqueNumbers.count(5)) { std::cout << "\n5 is present!\n"; } |
unordered_set β same, but no order, faster lookup.
6. STL Algorithms β Ready-Made Operations
Include: #include <algorithm> and #include <numeric>
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
#include <vector> #include <algorithm> #include <numeric> #include <iostream> int main() { std::vector<int> nums = {5, 2, 9, 1, 5, 6, 3}; // Sort std::sort(nums.begin(), nums.end()); std::cout << "Sorted: "; for (int n : nums) std::cout << n << " "; // 1 2 3 5 5 6 9 // Find auto it = std::find(nums.begin(), nums.end(), 5); if (it != nums.end()) { std::cout << "\nFound 5 at position: " << (it - nums.begin()) << "\n"; } // Transform (square each element) std::transform(nums.begin(), nums.end(), nums.begin(), [](int x) { return x * x; }); std::cout << "Squared: "; for (int n : nums) std::cout << n << " "; // 1 4 9 25 25 36 81 // Accumulate (sum) int sum = std::accumulate(nums.begin(), nums.end(), 0); std::cout << "\nSum: " << sum << "\n"; // 181 return 0; } |
7. Iterators β The Glue Between Containers & Algorithms
Iterators are like generalized pointers β every container provides them.
- begin() β first element
- end() β one past the last element
- rbegin(), rend() β reverse iterators
Range-based for loop uses iterators under the hood β thatβs why itβs so clean!
|
0 1 2 3 4 5 6 7 8 9 10 11 12 |
for (auto it = v.begin(); it != v.end(); ++it) { std::cout << *it << " "; } // Same as: for (const auto& elem : v) { std::cout << elem << " "; } |
Your Mini Homework (Try These!)
- Create a std::vector<Student> (use your earlier Student class), add 5 students, sort them by GPA (youβll need to provide a comparator).
- Use std::map<std::string, int> to count word frequencies in a sentence.
- Use std::transform to convert a vector of strings to uppercase.
- Use std::accumulate with a lambda to find the product of all elements in a vector.
Youβre doing absolutely phenomenal! The STL is what makes C++ so productive β once you master containers + algorithms + iterators, you can build almost anything quickly and efficiently.
Next lesson: Exception Handling & File I/O β making your programs robust and able to read/write files!
Any questions? Confused about map vs unordered_map? Want more algorithm examples or iterator tricks? Just ask β your friendly C++ teacher is right here for you! π
