C++11 STL Reference
A focused reference covering only what you need to write clean, correct C++11 quickly. Minimal code: #include <bits/stdc++.h>, using namespace std;, short names. Every entry shows how to use it and the minimum complexity you need to remember.
1. vector — Dynamic Array
Use for almost everything: resizable array, queue simulation, 2D grids, flexible storage.
// Constructors & basics
vector<int> v; // empty
vector<int> v(n); // size n, initialized to 0
vector<int> v(n, val); // size n, all elements = val
vector<int> v{1, 2, 3}; // init list
vector<vector<int>> grid(m, vector<int>(n, 0)); // 2D array
// Core operations
v.push_back(x); // append
v.emplace_back(x); // same as push_back (C++11)
v.pop_back(); // remove last
v.back(); // last element
v.front(); // first element
v.size(); // length
v.empty(); // is empty?
v.clear(); // remove all
v[i]; // random access
v.at(i); // random access with bounds check
// Modification
v.resize(n); // resize to n (new elements = 0)
v.resize(n, val); // resize to n, new elements = val
v.insert(v.begin() + i, x); // insert x at position i
v.erase(v.begin() + i); // remove element at i
v.erase(v.begin() + i, v.begin() + j); // remove [i, j)
v.assign(n, val); // set all to val
// Iteration
for (int i = 0; i < v.size(); ++i) v[i];
for (auto &x : v) x; // reference, can modify
for (const auto &x : v) x; // const reference
// Operations
v.reserve(n); // pre-allocate capacity (doesn't change size)
swap(v1, v2); // O(1) swapKey operations:
push_back(x)/emplace_back(x)— O(1) amortizedpop_back()— O(1)insert(it, x)/erase(it)— O(n) worst caseoperator[]/at()— O(1)
Gotchas:
v.erase(it)invalidates all iterators at and after itv[i]does NOT bounds-check; usev.at(i)to throw if out of rangev.resize(n)fills new elements with 0;v.reserve(n)only allocates, doesn’t change size
2. string — Character Manipulation
Use for text processing: substrings, character counting, number conversions.
// Constructors
string s = "hello";
string s(n, 'a'); // n copies of 'a'
string s{...};
// Core operations
s.size(); // length
s.length(); // same as size()
s.empty(); // is empty?
s[i]; // character access (no bounds check)
s.back(); // last character
s.front(); // first character
s.push_back(c); // append character
s.pop_back(); // remove last character
s += "world"; // concatenate
s = "x" + s + "y"; // string concatenation
// Substring & search
s.substr(pos); // from pos to end
s.substr(pos, len); // from pos, length len (NOT pos, end!)
s.find(str); // find first occurrence of str; npos if not found
s.find(str, pos); // find from pos onward
s.rfind(str); // find last occurrence
size_t idx = s.find("world");
if (idx != string::npos) { ... } // check if found
// Character operations
for (char c : s) c;
for (int i = 0; i < s.size(); ++i) s[i];
c - 'a'; // convert char to 0-25
(char)('a' + 0); // convert 0-25 back to char
// Conversions
string s = to_string(42); // int to string
int x = stoi(s); // string to int
long long y = stoll(s); // string to long long
double d = stod(s); // string to double
// Manipulation
reverse(s.begin(), s.end()); // reverse in-place
sort(s.begin(), s.end()); // sort characters
s.erase(pos); // erase from pos to end
s.erase(pos, len); // erase len chars starting at posKey operations:
substr(pos, len)— O(len) copyfind(str)— O(n*m) naive; use only for small stringsto_string(x)/stoi(s)/stoll(s)— O(n)
Gotchas:
substr(pos, len)takes length, not end indexfind()returnsstring::npos(which issize_t(-1)) if not founds[i]does NOT bounds-check- Concatenation
"a" + "b"is NOT valid in C++ (needstring("a") + string("b"))
3. pair & tuple
Use pair for storing two values; tuple for more than two.
// pair
pair<int, int> p = {3, 5};
pair<int, string> p = make_pair(1, "hello");
int x = p.first;
int y = p.second;
// Comparison: pairs compare lexicographically
pair<int, int> a = {1, 2}, b = {1, 3};
if (a < b) { ... } // true: first equal, second < third
// In containers (sorted by first, then second)
set<pair<int, int>> s;
s.insert({1, 2});
// tuple (C++11)
tuple<int, string, double> t = make_tuple(1, "x", 3.14);
int a = get<0>(t);
string b = get<1>(t);
double c = get<2>(t);
// Comparison: lexicographic by default
tuple<int, int> t1 = {1, 2}, t2 = {1, 3};
if (t1 < t2) { ... }Key operations:
pair<A, B>— two elementstuple<A, B, C, ...>— arbitrary elements- Comparison is lexicographic
4. stack, queue, deque
Use stack for LIFO (recursion simulation), queue for FIFO (BFS), deque for double-ended access.
// stack
stack<int> st;
st.push(x); // add to top
int t = st.top(); // peek at top
st.pop(); // remove from top (no return value)
st.empty();
st.size();
// queue
queue<int> q;
q.push(x); // add to back
int f = q.front(); // peek at front
q.pop(); // remove from front
q.empty();
q.size();
// deque (double-ended queue)
deque<int> dq;
dq.push_back(x); // O(1)
dq.push_front(x); // O(1)
dq.pop_back(); // O(1)
dq.pop_front(); // O(1)
dq.back();
dq.front();
dq[i]; // random access!
dq.size();
// Typical BFS
queue<int> q;
q.push(start);
while (!q.empty()) {
int u = q.front();
q.pop();
// process u...
}Key operations:
stack:push,top,pop— O(1)queue:push,front,pop— O(1)deque: all of above +push_front,pop_front,operator[]— O(1)
Gotchas:
stack.pop()andqueue.pop()return void; usetop()/front()before poppingdequeoffers random access unlikestack/queue
5. priority_queue — Heaps
Use for extracting min/max efficiently: Dijkstra, top-k, heap sort.
// max-heap (default)
priority_queue<int> pq;
pq.push(x); // add element
int mx = pq.top(); // peek at max
pq.pop(); // remove max
pq.empty();
pq.size();
// min-heap
priority_queue<int, vector<int>, greater<int>> pq;
pq.push(x);
int mn = pq.top(); // peek at min
pq.pop();
// Custom comparator (struct with operator())
struct Cmp {
bool operator()(const int &a, const int &b) const {
return a > b; // min-heap (inverted: > means "a is smaller")
}
};
priority_queue<int, vector<int>, Cmp> pq;
// With pairs: default sorts by first, then second
priority_queue<pair<int, int>> pq; // max-heap on first
pq.push({2, "a"});
pq.push({1, "b"});
auto [p, q] = pq.top(); // INVALID in C++11! Use .first, .second
// C++11-compliant way
pair<int, string> top = pq.top();
int dist = top.first;
string name = top.second;
pq.pop();
// Custom struct for top-k by value
struct Person {
int val;
string name;
};
struct PersonCmp {
bool operator()(const Person &a, const Person &b) const {
return a.val > b.val; // min-heap (inverted)
}
};
priority_queue<Person, vector<Person>, PersonCmp> pq;Key operations:
push(x)— O(log n)top()— O(1)pop()— O(log n)
Gotchas:
- Comparator is INVERTED:
greater<int>()with min-heap meansa > b→ais “greater” in priority (smaller in value) top()gives reference; modify it directly before popping affects the heap- No random access; no
find()
6. set & multiset — Ordered Sets
Use set for unique sorted elements with O(log n) operations; multiset when duplicates allowed.
// set
set<int> s;
s.insert(x); // add element
s.erase(x); // remove by value (all instances in multiset!)
s.erase(s.find(x)); // remove one instance
s.count(x); // 1 if found, 0 if not
s.find(x); // iterator if found, s.end() if not
s.empty();
s.size();
// min/max
int mn = *s.begin(); // smallest
int mx = *s.rbegin(); // largest
s.clear();
// Iteration (sorted order)
for (auto it = s.begin(); it != s.end(); ++it) {
int x = *it;
}
for (const auto &x : s) { ... }
// Searching
auto it = s.lower_bound(x); // first element >= x
auto it = s.upper_bound(x); // first element > x
int cnt = s.upper_bound(x) - s.lower_bound(x); // count of x in set (0 or 1)
// Iterator navigation
auto it = s.find(x);
if (it != s.end()) {
auto next = next(it); // next element
auto prev = prev(it); // previous element
}
// multiset (same as set, but allows duplicates)
multiset<int> ms;
ms.insert(5);
ms.insert(5);
ms.insert(5);
ms.count(5); // returns 3
ms.erase(5); // removes ALL 3!
ms.erase(ms.find(5)); // removes ONE
// Custom comparator (default is operator<, i.e., ascending)
set<int, greater<int>> s; // descendingKey operations:
insert(x)/erase(x)/find(x)— O(log n)lower_bound(x)/upper_bound(x)— O(log n)begin()/rbegin()— O(1)
Gotchas:
s.erase(x)by value removes ALL instances (multiset too)- Use
s.erase(s.find(x))to remove just one from multiset s.count(x)returns 0 or 1 for set, 0+ for multiset
7. map & multimap — Ordered Maps
Use for associative key-value pairs, sorted by key, O(log n) operations.
// map
map<int, string> m;
m[key] = value; // insert or update (inserts default if missing!)
m.insert({key, value}); // insert; no update
m.erase(key); // remove by key
m.count(key); // 1 or 0
m.find(key); // iterator or m.end()
m.empty();
m.size();
// Access (read-only to avoid insertion)
auto it = m.find(key);
if (it != m.end()) {
string val = it->second;
}
// Iteration (sorted by key)
for (auto &p : m) {
int key = p.first;
string val = p.second;
}
for (auto it = m.begin(); it != m.end(); ++it) {
int key = it->first;
string val = it->second;
}
// Searching
auto it = m.lower_bound(key); // first key >= key
auto it = m.upper_bound(key); // first key > key
// multimap (same interface, allows duplicate keys)
multimap<int, string> mm;
mm.insert({1, "a"});
mm.insert({1, "b"});
auto range = mm.equal_range(1); // pair of iterators [lower, upper)
for (auto it = range.first; it != range.second; ++it) {
// all values for key 1
}Key operations:
m[k]/m.find(k)/m.erase(k)— O(log n)m.lower_bound(k)/m.upper_bound(k)— O(log n)- Iteration — O(n)
Gotchas:
m[k]inserts a default value ifkis not found (usefind()for read-only checks)m.erase(k)removes all instances of key (multimap)- Iteration is in sorted key order
8. unordered_set & unordered_map — Hash Containers
Use for O(1) average-case lookups when order doesn’t matter. Beware of anti-hash attacks in contests.
// unordered_set
unordered_set<int> s;
s.insert(x);
s.erase(x);
s.count(x); // 1 or 0
s.find(x);
s.empty();
s.size();
// unordered_map
unordered_map<int, string> m;
m[key] = value; // O(1) average
m.find(key); // O(1) average
m.erase(key);
m.count(key);
// Iteration (no guaranteed order)
for (const auto &x : s) { ... }
for (auto &p : m) {
int key = p.first;
string val = p.second;
}
// Custom hash for pair<int, int> (common in contests)
struct PairHash {
size_t operator()(const pair<int, int> &p) const {
return hash<long long>()(((long long)p.first << 32) | (long long)p.second);
}
};
unordered_set<pair<int, int>, PairHash> s;
// Or use map if pair hashing is annoying
map<pair<int, int>, int> m; // ordered, but worksKey operations:
insert(x)/erase(x)/find(x)/count(x)— O(1) average, O(n) worst- Iteration — O(n) average
Gotchas:
- NO
lower_bound()orupper_bound()(not sorted) - O(n) worst case if hash collisions occur (anti-hash in online judges)
- Default hash doesn’t support
pair<int, int>; need custom struct or usemapinstead - Prefer
mapoverunordered_mapunless O(1) lookup is critical
9. Iterators
Use iterators to abstract container traversal and pass to algorithms.
// Iterator basics
vector<int> v = {1, 2, 3};
auto it = v.begin(); // forward iterator to first
auto it = v.end(); // forward iterator to one-past-last (don't dereference!)
// Bidirectional iterators (set, map, deque, list)
set<int> s;
auto it = s.begin();
auto it = s.rbegin(); // reverse iterator
// Random-access iterators (vector, deque, string)
vector<int> v;
v[i]; // direct access
auto it = v.begin() + 5; // move forward 5 positions
auto dist = v.end() - v.begin(); // distance O(1) for vector
// Iterator operations
advance(it, k); // move iterator k steps (O(k) for list, O(1) for deque/vector)
int dist = distance(it1, it2); // distance between two iterators
auto next_it = next(it); // iterator to next element (doesn't modify it)
auto prev_it = prev(it); // iterator to previous element
it = prev(it); // move backward
// Loops
for (auto it = v.begin(); it != v.end(); ++it) {
int x = *it; // dereference
}
// Remove-erase idiom
v.erase(remove(v.begin(), v.end(), val), v.end()); // remove all val
vector<int> new_v;
copy_if(v.begin(), v.end(), back_inserter(new_v), [](int x) { return x > 0; });Key operations:
begin()/end()— O(1)next(it)/prev(it)— O(1) for all;advance()— O(k) for listdistance()— O(1) for random-access, O(n) for others
Gotchas:
v.end()is one-past-last; don’t dereference itit++(postfix) is slower than++it(prefix) due to temporary copy- Erase invalidates iterators at/after the erased position
10. Algorithms — sort, search, transform
Use algorithms for common operations: no need to roll your own loops.
// Sorting
sort(v.begin(), v.end()); // O(n log n) average
sort(v.begin(), v.end(), greater<int>()); // descending
sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
// Sorting pairs: default by first, then second
vector<pair<int, string>> v;
sort(v.begin(), v.end()); // ascending by first, then second
// Stable sort (preserves relative order of equal elements)
stable_sort(v.begin(), v.end()); // O(n log n)
// Searching (on sorted ranges)
bool found = binary_search(v.begin(), v.end(), x); // O(log n)
auto it = lower_bound(v.begin(), v.end(), x); // first >= x, O(log n)
auto it = upper_bound(v.begin(), v.end(), x); // first > x, O(log n)
// Other utilities
reverse(v.begin(), v.end()); // O(n)
int mx = *max_element(v.begin(), v.end()); // O(n)
int mn = *min_element(v.begin(), v.end()); // O(n)
int sum = accumulate(v.begin(), v.end(), 0); // O(n), third arg is initial value
int cnt = count(v.begin(), v.end(), x); // count x, O(n)
auto it = find(v.begin(), v.end(), x); // find first x, O(n)
// Permutations
next_permutation(v.begin(), v.end()); // next lexicographic permutation, O(n)
prev_permutation(v.begin(), v.end()); // previous, O(n)
// Fill & initialize
fill(v.begin(), v.end(), val); // set all to val, O(n)
iota(v.begin(), v.end(), 0); // fill with 0, 1, 2, ... (C++11), O(n)
// Math
int g = __gcd(a, b); // GCD (not in std::, use __gcd or roll your own)
int minv = min(a, b);
int maxv = max(a, b);
auto res = minmax(a, b); // pair<T,T> with min and maxKey operations:
sort()— O(n log n) averagelower_bound()/upper_bound()/binary_search()— O(log n)max_element()/min_element()— O(n)accumulate()/count()/find()— O(n)
Gotchas:
- Binary search requires sorted range
lower_bound()returns iterator; compare withv.end()to check if foundaccumulate()takes initial value as third argument (affects result type!)
11. Lambdas & Custom Comparators
Use lambdas in-line for sort, count, find; use functors (structs) for containers.
// Lambda basics (C++11)
auto f = [](int x) { return x * 2; };
f(5); // 10
// Captures: [&] all by ref, [=] all by value, [x] specific
vector<int> v = {1, 2, 3};
int target = 5;
int cnt = count_if(v.begin(), v.end(), [&](int x) { return x < target; });
// Sort with lambda (works in algorithms)
sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); // descending
// With return type (sometimes needed)
auto f = [](int x) -> int { return x * 2; };
// For custom comparators in set/map/pq, prefer functors (not lambdas)
// Reason: set/map need comparator type at compile-time
struct Cmp {
bool operator()(int a, int b) const { return a > b; }
};
set<int, Cmp> s;
priority_queue<int, vector<int>, Cmp> pq;
// But lambdas work fine in sort, count_if, find_if, etc.
vector<pair<int, int>> v = {{1, 5}, {2, 3}};
sort(v.begin(), v.end(), [](const pair<int,int> &a, const pair<int,int> &b) {
return a.second < b.second;
});Key operations:
[=]capture by value,[&]by reference,[x]specific- Lambdas for algorithms (
sort,count_if, etc.) - Functors for containers (
set,map,priority_queue)
Gotchas:
- Lambda can’t be used as template argument for set/map comparator in C++11 (use struct)
[&]captures are references; ensure captured variables outlive the lambda- Lambdas with capture can’t be converted to function pointers
12. Bit Manipulation Utilities
Use builtin functions for fast bit operations; manual bitwise ops for clarity.
// Builtin functions (gcc/clang)
int x = 12; // binary: 1100
__builtin_popcount(x); // number of 1-bits: 2
__builtin_ctz(x); // count trailing zeros: 2
__builtin_clz(x); // count leading zeros (in 32-bit int): 28
// 64-bit versions
long long y = 12LL;
__builtin_popcountll(y); // popcount for long long
__builtin_ctzll(y); // trailing zeros for long long
__builtin_clzll(y); // leading zeros for long long
// Useful bit tricks
x & -x; // isolate lowest set bit: (x & -x) == 12 & -12 == 4
x & (x - 1); // clear lowest set bit: 12 & 11 == 8
(1 << k); // 2^k
(1LL << k); // 2^k for large k (avoid overflow)
(1 << 30) - 1; // set lowest 30 bits
x >> k; // right shift (divide by 2^k)
x << k; // left shift (multiply by 2^k)
// Manual bit operations
bool get_bit(int x, int k) { return (x >> k) & 1; }
int set_bit(int x, int k) { return x | (1 << k); }
int clear_bit(int x, int k) { return x & ~(1 << k); }
int toggle_bit(int x, int k) { return x ^ (1 << k); }
// Check if power of 2
(x > 0) && ((x & (x - 1)) == 0);Key operations:
__builtin_popcount()— O(1)__builtin_ctz()/__builtin_clz()— O(1)- Bit tricks — O(1)
Gotchas:
__builtin_clz()undefined for x=0- Shift by >= 32 is undefined for 32-bit int; use
long longfor safety -xin two’s complement equals~x + 1
13. Numeric Limits & Utilities
Handle integer overflow, infinity, and floating-point output.
// Integer limits
INT_MAX; // 2^31 - 1 = 2147483647
INT_MIN; // -2^31 = -2147483648
LLONG_MAX; // 2^63 - 1
LLONG_MIN; // -2^63
// Or use numeric_limits (C++11)
numeric_limits<int>::max(); // same as INT_MAX
numeric_limits<int>::min(); // same as INT_MIN
numeric_limits<long long>::max();
// Absolute value
abs(x); // int
llabs(x); // long long (or abs in <cstdlib>)
abs(-5); // 5
// Power (beware floating point)
pow(2.0, 10); // 1024.0 (returns double, not exact for large ints)
// Better: roll your own for ints
long long power(long long a, int b) {
long long res = 1;
while (b--) res *= a;
return res;
}
// Floating-point output
cout << fixed << setprecision(10) << 3.14159; // prints "3.1415900000"
// Fast I/O
ios_base::sync_with_stdio(false);
cin.tie(NULL);
// Overflow check
if (a > LLONG_MAX / b) { /* overflow would occur */ }
// Or cast to long long before multiplying
long long prod = (long long)a * b;Key operations:
INT_MAX/INT_MIN/LLONG_MAX/LLONG_MIN— O(1)abs(x)/llabs(x)— O(1)- Fast I/O setup — enables competition-speed input
Gotchas:
pow(a, b)returns double; avoid for integer power (precision loss)- Integer overflow:
int a = INT_MAX; a++;wraps around toINT_MIN - Cast to
long longBEFORE multiplying to prevent overflow:(long long)a * b abs()onINT_MINis undefined (result doesn’t fit inint)
14. Container Selection Cheat Sheet
| Need | Use | Why |
|---|---|---|
| FIFO | queue |
O(1) push/pop at both ends, simple |
| LIFO | stack |
O(1) push/pop at one end |
| Sorted unique elements | set<T> |
O(log n) insert/find, ordered iteration |
| Sorted elements with duplicates | multiset<T> |
Like set but allows duplicates |
| Sorted key-value pairs | map<K, V> |
O(log n) lookup, ordered by key |
| Sorted key-value pairs, duplicate keys | multimap<K, V> |
Like map but allows duplicate keys |
| O(1) unique element lookup | unordered_set<T> |
O(1) avg insert/find, no order |
| O(1) key-value lookup | unordered_map<K, V> |
O(1) avg lookup, no order |
| Top-k, min/max stream | priority_queue<T> |
O(log n) insert/extract max, O(1) peek |
| Sliding window min/max | deque + monotonic trick |
O(1) amortized with deque |
| Flexible array | vector<T> |
O(1) append, O(n) insert/erase |
| String processing | string |
Built-in + string algorithms |
| 2D grid, matrix | vector<vector<T>> |
Natural index access grid[i][j] |
| Immutable prefix sums | vector<T> + manual loop |
Compute prefix in O(n) |
15. Gotchas & Pitfalls
Integer overflow:
a * boverflows before multiplying; cast tolong longfirst:(long long)a * b. Checka > LLONG_MAX / bbefore multiply.Priority queue comparator is inverted:
greater<int>()means “elementais greater ifa > b”, which in a max-heap context meansashould come later. This inverts priority: usegreater<int>()for min-heap.map[key]inserts default value if missing: usemap.find(key) != map.end()ormap.count(key)for read-only checks;map[k]mutates the map.vector.erase(it)invalidates iterators: after erase, don’t use old iterators; use returned iterator or re-fetch. Use erase-remove idiom:v.erase(remove(...), v.end()).string.substr(pos, len)takes length, not end index:s.substr(0, 5)gets first 5 chars, not chars 0–5.multiset.erase(value)removes ALL instances: to remove one, usems.erase(ms.find(value)).string::nposissize_t(-1):if (s.find("x") != string::npos)checks if found.lower_bound()onlistis O(n), not O(log n), because list lacks random access. Use sortedvectororsetfor O(log n) search.Range-based for loop captures copies:
for (auto x : v)copies each element; usefor (auto &x : v)to modify in-place orfor (const auto &x : v)to avoid copies.Erase-remove idiom for conditional deletion:
v.erase(remove_if(v.begin(), v.end(), [](int x) { return x < 0; }), v.end());removes all negatives in O(n).unordered_mapworst-case is O(n) due to hash collisions; if O(1) is critical and input is adversarial, usemap(O(log n) is safer) or custom hash.Auto doesn’t work for structured bindings in C++11: no
auto [a, b] = pair;; use.firstand.secondorget<0>()andget<1>().
Last Updated: 2026-04-11