C++ Cheatsheet
STL Containers
Use this C++ reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
Container Overview
| Container | Header | Ordered? | Access | Insert/Erase | Use when |
|---|---|---|---|---|---|
vector<T> | <vector> | sequence | O(1) random | O(1) back, O(n) mid | dynamic array, most-used default |
deque<T> | <deque> | sequence | O(1) random | O(1) front+back, O(n) mid | queue with random access |
list<T> | <list> | sequence | O(n) | O(1) anywhere (with iterator) | frequent mid-insert/erase |
forward_list<T> | <forward_list> | sequence | O(n) | O(1) after position | singly-linked; minimal memory |
array<T,N> | <array> | sequence | O(1) random | fixed size | C-array replacement |
stack<T> | <stack> | adapter | top only | O(1) push/pop | LIFO |
queue<T> | <queue> | adapter | front/back | O(1) push/pop | FIFO |
priority_queue<T> | <queue> | adapter | max top | O(log n) push/pop | heap / scheduling |
set<K> | <set> | sorted | O(log n) | O(log n) | sorted unique keys |
multiset<K> | <set> | sorted | O(log n) | O(log n) | sorted keys with duplicates |
map<K,V> | <map> | sorted | O(log n) | O(log n) | sorted key-value |
multimap<K,V> | <map> | sorted | O(log n) | O(log n) | sorted kv, duplicate keys |
unordered_set<K> | <unordered_set> | hash | O(1) avg | O(1) avg | fast unique membership |
unordered_multiset<K> | <unordered_set> | hash | O(1) avg | O(1) avg | fast membership, duplicates |
unordered_map<K,V> | <unordered_map> | hash | O(1) avg | O(1) avg | fast key-value lookup |
unordered_multimap<K,V> | <unordered_map> | hash | O(1) avg | O(1) avg | fast kv, duplicate keys |
span<T> | <span> | view | O(1) | non-owning | non-owning range view (C++20) |
string_view | <string_view> | view | O(1) | non-owning | cheap string reference |
vector<T>
#include <vector> std::vector<int> v; std::vector<int> v2(5); // 5 elements, value-initialized (0) std::vector<int> v3(5, 42); // 5 elements, each 42 std::vector<int> v4 = {1, 2, 3}; // initializer list std::vector<int> v5(v4); // copy std::vector<int> v6(std::move(v4)); // move (v4 emptied) // Capacity / size v.size(); // number of elements v.empty(); // true if size == 0 v.capacity(); // allocated capacity v.reserve(100); // allocate at least 100 (no new elements) v.resize(10); // set size to 10 (new elements value-init) v.resize(10, 99); // new elements = 99 v.shrink_to_fit(); // release excess capacity // Element access v[i]; // no bounds check (UB if out of range) v.at(i); // bounds-checked; throws std::out_of_range v.front(); // first element v.back(); // last element v.data(); // raw pointer to first element // Modifiers v.push_back(42); // append copy v.push_back(std::move(x)); // append move v.emplace_back(42); // construct in-place (no copy) v.pop_back(); // remove last (no return) v.insert(v.begin() + 2, 99); // insert at position v.insert(v.end(), {7, 8, 9}); // insert range v.emplace(v.begin() + 1, 42); // emplace at position v.erase(v.begin() + 2); // erase one element v.erase(v.begin(), v.begin() + 3); // erase range v.clear(); // remove all elements v.assign(5, 0); // replace contents // Iteration for (auto& x : v) { /* ... */ } for (auto it = v.begin(); it != v.end(); ++it) { *it; } v.rbegin(); v.rend(); // reverse iterators v.cbegin(); v.cend(); // const iterators
array<T, N>
#include <array> std::array<int, 4> a = {1, 2, 3, 4}; std::array<int, 4> b{}; // zero-initialized a[i]; a.at(i); a.front(); a.back(); a.size(); // always N (constexpr) a.empty(); // true only if N == 0 a.data(); // raw pointer a.fill(0); // set all to 0 std::swap(a, b); // O(N) element-wise swap
deque<T>
#include <deque> std::deque<int> d = {1, 2, 3}; d.push_back(4); d.push_front(0); d.pop_back(); d.pop_front(); d[i]; d.at(i); d.front(); d.back(); d.insert(d.begin() + 1, 99); d.erase(d.begin());
list<T> and forward_list<T>
#include <list> std::list<int> lst = {1, 2, 3}; lst.push_back(4); lst.push_front(0); lst.pop_back(); lst.pop_front(); lst.front(); lst.back(); // Only list (not forward_list) has back() and reverse iterators auto it = std::find(lst.begin(), lst.end(), 2); lst.insert(it, 99); // insert BEFORE it lst.erase(it); lst.sort(); // O(n log n) sort (std::sort needs random-access) lst.sort(std::greater<>{}); lst.reverse(); lst.unique(); // remove consecutive duplicates lst.remove(2); // remove all elements == 2 lst.remove_if([](int x){ return x < 0; }); lst.merge(other); // merge two sorted lists (other emptied) lst.splice(it, other); // move elements from other #include <forward_list> std::forward_list<int> fl = {1, 2, 3}; fl.push_front(0); fl.pop_front(); fl.insert_after(fl.begin(), 99); fl.erase_after(fl.begin()); fl.before_begin(); // iterator before first element
stack<T> and queue<T>
#include <stack> std::stack<int> st; st.push(1); st.push(2); st.top(); // peek (no pop) st.pop(); // remove top (returns void) st.empty(); st.size(); #include <queue> std::queue<int> q; q.push(1); q.push(2); q.front(); // peek front q.back(); // peek back q.pop(); // remove front (returns void) q.empty(); q.size();
priority_queue<T>
#include <queue> // Max-heap by default std::priority_queue<int> pq; pq.push(3); pq.push(1); pq.push(4); pq.top(); // 4 (max) pq.pop(); pq.empty(); pq.size(); // Min-heap std::priority_queue<int, std::vector<int>, std::greater<int>> minPQ; // Custom comparator auto cmp = [](const std::pair<int,int>& a, const std::pair<int,int>& b){ return a.second > b.second; // min by second }; std::priority_queue<std::pair<int,int>, std::vector<std::pair<int,int>>, decltype(cmp)> custom(cmp);
set<K> and multiset<K>
#include <set> std::set<int> s = {3, 1, 4, 1, 5}; // duplicates ignored: {1,3,4,5} s.insert(2); // returns pair<iterator, bool> s.insert({6, 7}); s.erase(3); // erase by value s.erase(s.begin()); // erase by iterator s.count(4); // 0 or 1 for set s.find(4); // iterator or s.end() s.contains(4); // bool (C++20) s.lower_bound(3); // first >= 3 s.upper_bound(3); // first > 3 s.equal_range(3); // pair of iterators // Custom comparator std::set<int, std::greater<int>> desc; // descending std::multiset<int> ms; ms.insert(3); ms.insert(3); // duplicates allowed ms.count(3); // can be > 1 ms.erase(ms.find(3)); // erase just ONE occurrence
map<K,V> and multimap<K,V>
#include <map> std::map<std::string, int> m; m["alice"] = 30; // insert or update via subscript m.insert({"bob", 25}); // returns pair<iterator, bool> m.insert_or_assign("alice", 31); // always overwrites (C++17) m.emplace("carol", 28); m.try_emplace("dave", 22); // only inserts if key absent (C++17) m.at("alice"); // throws if absent m["missing"]; // inserts default value (!) m.count("alice"); // 0 or 1 m.find("alice"); // iterator or m.end() m.contains("alice"); // bool (C++20) m.erase("alice"); m.lower_bound("b"); m.upper_bound("b"); m.equal_range("b"); for (auto& [key, val] : m) { /* sorted by key */ } // Merge (C++17) — move nodes from source without reallocation m.merge(other); std::multimap<std::string, int> mm; mm.insert({"k", 1}); mm.insert({"k", 2}); // duplicate keys OK mm.count("k"); // 2 auto range = mm.equal_range("k"); for (auto it = range.first; it != range.second; ++it) { it->second; }
unordered_map<K,V> and unordered_set<K>
#include <unordered_map> #include <unordered_set> std::unordered_map<std::string, int> um; um["a"] = 1; um.insert({"b", 2}); um.insert_or_assign("a", 99); um.try_emplace("c", 3); um.at("a"); um["missing"]; um.count("a"); um.find("a"); um.contains("a"); um.erase("a"); um.size(); um.empty(); um.clear(); // Bucket interface (for tuning) um.bucket_count(); um.load_factor(); um.max_load_factor(0.7f); um.rehash(100); // at least 100 buckets um.reserve(50); // rehash for at least 50 elements // Custom hash struct MyHash { std::size_t operator()(const MyKey& k) const noexcept { return std::hash<int>{}(k.id) ^ (std::hash<std::string>{}(k.name) << 1); } }; std::unordered_map<MyKey, int, MyHash> custom; std::unordered_set<int> us = {1, 2, 3}; us.insert(4); us.erase(2); us.count(3); // 0 or 1 us.contains(3);
Common Operations Across Containers
// Iteration — works for all standard containers for (auto& x : container) { /* x is the element (value_type) */ } // Size container.size(); // current number of elements container.empty(); // true if size() == 0 container.max_size();// theoretical maximum // Clear container.clear(); // Swap a.swap(b); // O(1) pointer swap — except std::array: O(N) element-wise std::swap(a, b); // same // Erase-remove idiom (pre-C++20) v.erase(std::remove(v.begin(), v.end(), val), v.end()); // C++20 std::erase / std::erase_if #include <vector> // (also available for other containers) std::erase(v, val); // remove all == val std::erase_if(v, [](int x){ return x < 0; }); // remove if pred
std::pair and std::tuple
#include <utility> std::pair<int, std::string> p = {1, "a"}; p.first; p.second; auto [a, b] = p; // structured binding (C++17) std::make_pair(1, "a"); #include <tuple> std::tuple<int, double, std::string> t = {1, 3.14, "hi"}; std::get<0>(t); std::get<1>(t); std::get<2>(t); std::get<double>(t); // by type (C++14, unique types only) auto [x, y, z] = t; std::make_tuple(1, 3.14, "hi"); std::tie(x, y, z) = t; // assign to existing variables std::tuple_size_v<decltype(t)>; // 3