HomebaseWorks
Lesson 3 of 4

STL in practice: vector, map, set and iterators

Use vector, map, unordered_map and set correctly, search with find, erase while iterating, and avoid the operator[] insert trap.

EWritten by the HomebaseWorks editorial team · reviewed 26 Oct 2026

Day-to-day C++ is mostly standard containers and algorithms, and screenings test whether you know their behaviour rather than their full interface. Four containers, a handful of algorithms and the iterator rules cover nearly every question.

Advertisement

vector: the default container

std::vector<int> v = {5, 1, 4};
v.push_back(9);                      // size 4, v.back() is 9
std::sort(v.begin(), v.end());
for (int n : v) std::cout << n << " ";                               // 1 4 5 9
auto it = std::find(v.begin(), v.end(), 4);
if (it != v.end()) std::cout << "found";
v.erase(std::remove(v.begin(), v.end(), 5), v.end());
std::cout << v.size();                                               // 3

v[i] does no bounds check; v.at(i) throws std::out_of_range. std::remove only moves unwanted items to the end and returns the new logical end; you must call erase to shrink the vector.

map, unordered_map and set

std::map<std::string, int> stock;
stock["pen"] = 10;
stock["ink"] = 3;
std::cout << stock.count("pen") << " " << stock.count("tape") << "\n";  // 1 0
std::cout << stock["tape"] << " " << stock.size() << "\n";  // 0 3  <- inserted "tape"
for (const auto& [name, qty] : stock) std::cout << name << "=" << qty << " ";
// ink=3 pen=10 tape=0  (map is sorted by key)

map keeps keys sorted and gives logarithmic lookups; unordered_map is hash based, usually faster, and has no order. Reading a missing key with operator[] inserts a default value, which is handy for counting and dangerous when you only meant to look. Use find or count for lookups, and at when a missing key is an error. counts[w]++ is the idiomatic word counter precisely because the first access inserts a zero. A set drops duplicates and keeps its elements sorted, so std::set<int>{3, 1, 3, 2} has size 3 and begins with 1.

Iterators and invalidation

std::vector<int> e = {1, 2, 3, 4};
for (auto i = e.begin(); i != e.end(); ) {
    if (*i % 2 == 0) i = e.erase(i);   // erase returns the next valid iterator
    else ++i;
}
std::cout << e.size();   // 2

push_back can reallocate a vector, which makes every pointer and iterator into it invalid. erase invalidates iterators at and after the removed element, so always use its return value. Node-based containers such as map and list keep other iterators valid when you erase one element.

Common mistakes and a practice habit

  • Writing if (stock["tape"] > 0) and silently adding a key.
  • Calling ++i after erase(i) in the same loop, which skips an element or crashes.
  • Dereferencing the result of find without comparing it to end().
  • Expecting std::remove to change size().

Practice habit: Write a word-count program that reads words into an unordered_map, copies the entries into a vector of pairs, sorts by count, and prints the top five. It is twenty lines, uses every rule above, and is a frequent live-coding exercise.

Advertisement
Continue with C++4 lessons · 1 interview set · 1 test · 1 certificate
Not tested

More in Programming