STL Containers
STL Containers
When to use vectors, arrays, maps, sets, queues, and container adapters.
STL Containers
When to use vectors, arrays, maps, sets, queues, and container adapters.
std::array<T, N>: fixed-size wrapper over stack-style storagestd::vector<T>: dynamic contiguous storage, default first choicestd::deque<T>: efficient push/pop at both endsstd::list<T>: linked list, rarely the best optionstd::forward_list<T>: singly linked liststd::vector<int> values{1, 2, 3};
values.reserve(16);
For most dynamic sequences, std::vector is the default because contiguous storage is simple, cache-friendly, and broadly compatible with algorithms.
std::set<T> / std::multiset<T>std::map<K, V> / std::multimap<K, V>Tree-based and ordered by key.
std::map<std::string, int> counts;
counts["Ada"] = 1;
std::unordered_set<T>std::unordered_map<K, V>Hash-based with average constant-time lookup.
std::unordered_map<std::string, int> counts;
counts["Ada"] = 1;
Choose unordered containers when fast lookup matters more than sorted traversal.
std::stack<T>std::queue<T>std::priority_queue<T>Adapters intentionally hide some underlying-container operations so the API matches the data-structure role more closely.
std::vector<int> values{1, 2, 3};
values.push_back(4);
values.emplace_back(5);
values.erase(values.begin());
for (auto it = values.begin(); it != values.end(); ++it) {
std::cout << *it << '\n';
}
std::vectorstd::array when size is fixed at compile timestd::unordered_map for fast key lookup when ordering is irrelevantstd::vectorstd::arraystd::mapstd::unordered_mapstd::queuestd::priority_queuestd::vector: insert/erase may invalidate iterators and references after the changed position; reallocation invalidates all of them.std::deque: middle insert/erase can invalidate many iterators.std::list and std::forward_list: iterators stay valid except for erased elements.When container choice affects references, iterators, or views held elsewhere in the program, invalidation rules often matter more than raw big-O complexity.
std::map::operator[] when you only want to check existence (it inserts a default value)std::map or std::set (they do not support reserve)std::list by default rather than std::vector (linked lists are rarely faster in practice due to cache effects)emplace_back constructs in-place, while push_back copies or movesvoid render(std::span<const int> pixels);
std::mdspan<float, std::extents<std::size_t, 4, 4>> matrix(view_ptr);
std::span gives a lightweight view over contiguous data.std::mdspan is a C++23 multidimensional non-owning view.emplace_back when constructing elements directly in place.reserve() when you know approximate vector growth.flat_map style containers only through external libraries when profiling justifies them.std::list for performance without measuringreserve() for obviously growing vectors#include <vector>
int main() {
std::vector<int> values{1, 2, 3};
values.push_back(4);
return values.back();
}
Swap `std::vector` for `std::deque` or `std::unordered_map` in a toy example and note what changes in iteration, lookup, and invalidation rules.
#include <deque>
int main() {
std::deque<int> values{1, 2, 3};
values.push_front(0);
return values.front();
}