Ch21: STL & Ranges¶
TL;DR: STL Containers & Adaptors: C++ standard containers offer standardized contiguous arrays (
vector,array), linked lists (list,forward_list), ordered/unordered trees and hashes (set,map), and LIFO/FIFO interface adaptors (stack,queue,priority_queue). | Unlike sequence containers (vector,list) which store elements by position, associative containers (map,set, and theirunordered_variants) store elements by key, giving fast lookup at the cost of no guaranteed insertion order (for theunordered_family) or sorted order (for the ordered family).
⚡ Quick Reference¶
#include <iostream>
#include <vector>
#include <array>
#include <deque>
#include <list>
#include <forward_list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <stack>
#include <queue>
#include <algorithm>
#include <ranges>
int main() {
std::vector<int> v = {10, 20, 30};
std::array<int, 3> arr = {1, 2, 3};
auto start = v.begin();
auto stop = v.end();
std::deque<int> d = {1, 2};
std::list<int> lst = {5, 6};
std::forward_list<int> fl = {7, 8};
std::set<int> s = {3, 1, 2};
std::map<int, std::string> m = {{1, "one"}};
std::ranges::sort(v);
auto lazy_view = v | std::views::filter([](int x){ return x > 10; })
| std::views::transform([](int x){ return x * 2; });
return 0;
}
Associative Containers¶
#include <iostream>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <string>
int main() {
// std::map<K, V> - sorted by key (red-black tree), O(log n) operations
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages.insert({"Bob", 25});
// .find() - returns iterator, or .end() if not found (never throws)
if (auto it = ages.find("Alice"); it != ages.end()) {
std::cout << it->first << " is " << it->second << '\n';
}
// .at() - throws std::out_of_range if key missing (vs operator[] which inserts a default)
try {
std::cout << ages.at("Charlie") << '\n';
} catch (const std::out_of_range&) {
std::cout << "Charlie not found\n";
}
// std::set<T> - sorted, unique elements only
std::set<int> uniqueNums{5, 3, 5, 1, 3}; // duplicates silently dropped -> {1, 3, 5}
// std::unordered_map<K, V> - hash table, O(1) average lookup, no ordering guarantee
std::unordered_map<std::string, int> fastLookup;
fastLookup["x"] = 1;
// std::unordered_set<T> - hash table version of set
std::unordered_set<int> fastUnique{5, 3, 5, 1};
// Range-based iteration over a map yields key-value pairs
for (const auto& [name, age] : ages) {
std::cout << name << ": " << age << '\n';
}
return 0;
}
🧠 Core Concepts¶
- STL Containers & Adaptors: C++ standard containers offer standardized contiguous arrays (
vector,array), linked lists (list,forward_list), ordered/unordered trees and hashes (set,map), and LIFO/FIFO interface adaptors (stack,queue,priority_queue). - Ranges & Adaptor Views: C++20 ranges (
std::ranges) replace iterator pairs with full container algorithms. Views (filter,transform,take,iota) provide lazy, zero-overhead compile-time pipelining via the|operator. - Custom Iterator Protocols: Custom containers integrate with STL algorithms by defining five type aliases (
iterator_category,value_type,difference_type,pointer,reference) and implementing dereference, increment, and comparison operators. - Ordered vs Unordered:
std::map/std::setmaintain elements sorted by key (typically via a red-black tree), givingO(log n)operations and in-order iteration.std::unordered_map/std::unordered_setuse a hash table forO(1)average-case operations but no ordering guarantee. - Key Uniqueness:
map/set/unordered_map/unordered_setall require unique keys — inserting a duplicate key is a no-op (the existing element stays). Use themultimap/multisetvariants when duplicate keys are needed. operator[]vs.at():operator[]on amapsilently default-constructs and inserts a new element if the key doesn't exist — convenient but can hide bugs..at()throwsstd::out_of_rangeinstead, making missing-key bugs loud and catchable.- Structured Bindings with Maps: Iterating a
mapyieldsstd::pair<const Key, Value>elements;for (const auto& [key, value] : myMap)unpacks them cleanly (C++17 and later).
⚠️ Pitfalls (Quick Scan)¶
| Mistake | Fix |
|---|---|
Constructing vectors with braced initializer lists (e.g., vector<int>{20, 55}) to pre-size them |
Use parentheses construction vector<int>(20, 55) for size-based initialization |
Dereferencing or advancing iterators past the end() boundary |
Always verify it != container.end() before dereferencing |
Inserting or erasing elements from a vector while using active iterators |
Re-evaluate iterator positions or assign returned iterators from insertion/deletion methods |
Accessing missing keys in std::map using operator[] |
Use .find() or .at() for read-only lookups, reserving operator[] for writes |
Using std::copy or std::transform on unallocated destination containers |
Pre-size destination containers or wrap the destination in std::back_inserter to grow dynamically |
Providing a non-strict weak ordering comparator (e.g., <=) to std::sort |
Always use strict inequality < (not <=) in custom sorting comparators |
Failing to pair std::views::iota with a termination condition |
Combine iota with a terminating adapter like std::views::take |
| Implementing a custom iterator post-increment without returning a copy | Create a temporary copy of the current state, increment, and return the temporary |
| Failing to define separate mutable and const custom iterator types | Implement a distinct ConstIterator class or use raw const T* pointers for const containers |
Using operator[] to check if a key exists |
This inserts a default-constructed value as a side effect — use .find() or .contains() instead |
Expecting unordered_map iteration order to be stable/insertion order |
No ordering guarantee at all — use std::map if order matters |
| Assuming duplicate insert overwrites the existing value | insert() is a no-op on duplicate keys — use operator[] or insert_or_assign() to overwrite |
Using a mutable custom struct as a std::set element and mutating it |
Mutating in place breaks the tree's sort invariant; erase and reinsert instead |
Forgetting a hash specialization for custom types in unordered_map/unordered_set |
Provide std::hash<T> specialization or a custom hasher, or compilation fails |
📖 Full Details¶
Cause → Effect → Fix with timestamp (click to expand)
* **Constructing vectors with braced initializer lists (e.g., `vector📎 Repo Files¶
43.StlContainersAndIterators/43.2StdVector/main.cpp43.StlContainersAndIterators/43.3StdArray/main.cpp43.StlContainersAndIterators/43.4Iterators/main.cpp43.StlContainersAndIterators/43.6ReverseIterators/main.cpp43.StlContainersAndIterators/43.7ContantIterators/main.cpp43.StlContainersAndIterators/43.9StdBeginStdEnd/main.cpp44.ZoomingOnSTLContainers/44.2Deque/main.cpp44.ZoomingOnSTLContainers/44.3ForwardList/main.cpp44.ZoomingOnSTLContainers/44.4List/main.cpp44.ZoomingOnSTLContainers/44.5Vector/main.cpp44.ZoomingOnSTLContainers/44.6Array/main.cpp44.ZoomingOnSTLContainers/44.8Pair/main.cpp44.ZoomingOnSTLContainers/44.9Set/main.cpp44.ZoomingOnSTLContainers/44.10Map/main.cpp44.ZoomingOnSTLContainers/44.11MultisetMultimap/main.cpp44.ZoomingOnSTLContainers/44.12UnorderedSetUnorderedMap/main.cpp44.ZoomingOnSTLContainers/44.14Stack/main.cpp44.ZoomingOnSTLContainers/44.15Queue/main.cpp44.ZoomingOnSTLContainers/44.16PriorityQueue/main.cpp45.StlAlgorithms/45.2AllOf/main.cpp45.StlAlgorithms/45.3ForEach/main.cpp45.StlAlgorithms/45.4.MaxEltMinElt/main.cpp45.StlAlgorithms/45.5FindAndFindIf/main.cpp45.StlAlgorithms/45.6Copy/main.cpp45.StlAlgorithms/45.7Sort/main.cpp45.StlAlgorithms/45.8Transform/main.cpp46.RangesLibraryInCpp20/46.2RangeAlgorithms/main.cpp46.RangesLibraryInCpp20/46.4Projections/main.cpp46.RangesLibraryInCpp20/46.5ViewsAndRangeAdaptors/main.cpp46.RangesLibraryInCpp20/46.6ViewCompositionAndPipeOperator/main.cpp46.RangesLibraryInCpp20/46.7RangeFactories/main.cpp47.BuildingIteratorsForCustomContainers/40.02.IteratorPowers/main.cpp47.BuildingIteratorsForCustomContainers/40.04CustomInputIterator/main.cpp47.BuildingIteratorsForCustomContainers/40.05CustomOutputIterator/main.cpp47.BuildingIteratorsForCustomContainers/40.06CustomForwardIterator/main.cpp47.BuildingIteratorsForCustomContainers/40.07CustomBidirectionalIteator/main.cpp47.BuildingIteratorsForCustomContainers/40.08CustomRandomAccessIterator/main.cpp47.BuildingIteratorsForCustomContainers/40.09CustomIteratorsWithViews/main.cpp47.BuildingIteratorsForCustomContainers/40.10ConstantIterators/main.cpp47.BuildingIteratorsForCustomContainers/40.11RawPointersAsIterators/main.cpp47.BuildingIteratorsForCustomContainers/40.12WrappingIteratorsFromOtherContainers/main.cpp43.StlContainersAndIterators/main.cpp44.ZoomingOnSTLContainers/main.cpp