Back to C++
2026-02-088 min read

C++ Standard Template Library

Learn C++ Standard Template Library step by step with clear examples and exercises.

Title: Mastering the C++ Standard Template Library (STL)

Why This Matters

The C++ Standard Template Library (STL) is an integral part of modern C++ programming, offering a collection of templates and data structures that simplify coding, increase efficiency, and promote code reusability. Understanding STL is crucial for writing efficient and modern C++ programs, especially in competitive programming and software development interviews.

Prerequisites

Before delving into the Standard Template Library, you should be familiar with:

  • Basic C++ concepts such as variables, data types, operators, loops, functions, classes, and object-oriented programming principles
  • Understanding of algorithms and data structures
  • Familiarity with fundamental concepts like pointers, references, and exception handling
  • A strong foundation in C++ syntax and programming techniques

Core Concept

The C++ Standard Template Library (STL) consists of four main components:

  1. Containers: These are collections of elements that can store and manage data efficiently. STL provides several container classes such as vector, list, deque, array, set, multiset, map, unordered_map, forward_list, etc. Each container has its unique properties, use cases, and specific iterators.

Container Properties

  • Dynamic vs Static: Containers like vector and deque are dynamic arrays that can grow or shrink as needed, while containers like array have a fixed size at creation.
  • Ordered vs Unordered: Ordered containers (like vector, list, deque, and forward_list) maintain the insertion order of elements, whereas unordered containers (like set, multiset, unordered_map, and unordered_set) do not.
  • Duplicate values: Some containers (like vector and deque) allow duplicate values, while others (like set and multiset) do not.
  • Efficiency: The efficiency of container operations like insertion, deletion, and searching varies between different container types. Understanding the specific properties of each container is essential for choosing the most appropriate one for a given task.
  1. Iterators: Iterators allow traversing through the containers and accessing their elements. They provide a uniform way to traverse different types of containers, making it easier to write generic algorithms. STL offers several iterator categories: InputIterator, OutputIterator, ForwardIterator, BidirectionalIterator, RandomAccessIterator, and ReverseIterator.

Iterator Categories

  • Input Iterators: Can only read data from the container. Examples include std::vector::const_iterator and std::list::const_iterator.
  • Output Iterators: Can write data to the container but cannot read or modify their own value. Examples include std::back_insert_iterator> and std::ostream_iterator.
  • Forward Iterators: Can be incremented and dereferenced, allowing reading data from the container. Examples include std::vector::iterator and std::list::iterator.
  • Bidirectional Iterators: In addition to forward iteration, can also decrement and access previous elements. Examples include std::list::iterator, std::deque::iterator, and std::vector::reverse_iterator.
  • Random Access Iterators: Can be used with arithmetic operations like addition and subtraction to access elements directly. Examples include std::vector::iterator and std::array::iterator.
  • Reverse Iterators: Traverse containers in the reverse order, starting from the end. Examples include std::vector::reverse_iterator and std::list::reverse_iterator.
  1. Algorithms: STL provides a set of predefined algorithms that can be used on the containers to perform various operations like searching, sorting, modifying, etc. Some popular algorithms include sort, find, reverse, remove, copy, swap, and many more. Algorithms can also work with arrays and other custom data structures when adapted accordingly.

Algorithm Categories

  • Non-modifying algorithms: Perform operations like searching or comparing without modifying the container, such as std::find and std::equal.
  • Modifying algorithms: Modify the container by adding, removing, or rearranging elements, such as std::sort, std::reverse, and std::remove.
  • Iterators-based algorithms: Operate on iterators instead of specific containers, allowing them to work with custom data structures. Examples include std::for_each and std::transform.
  1. Function objects (Functors): Function objects are classes that overload the operator() function, allowing them to be used as functions in expressions. STL provides several predefined functors like greater, less, plus, etc., which can be used with algorithms for custom comparisons and manipulations.

Functor Usage

  • Custom Comparators: Use a std::greater or std::less functor to sort containers in descending or ascending order, respectively.
  • Custom Manipulators: Use a std::plus functor to perform custom operations like adding two vectors element-wise.

Worked Example

Let's create a simple program that uses the vector container, push_back function, begin() and end() functions to access iterators, the sort algorithm, and the for_each algorithm to print each element:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

int main() {
std::vector<int> numbers = {5, 3, 1, 4, 2};

// Adding an element to the end of the vector
numbers.push_back(6);

// Sorting the vector using the sort algorithm
std::sort(numbers.begin(), numbers.end());

// Using for_each algorithm to print each element
auto print = [](const int& number) {
std::cout << number << " ";
};

std::for_each(numbers.begin(), numbers.end(), print);

return 0;
}

Common Mistakes

  1. Forgetting to include necessary headers: Make sure you include the appropriate header files like `, , , and `.
  2. Incorrect iterator usage: Iterators should be used correctly when traversing containers, and their validity should be checked before using them. Be aware of iterator categories and the operations they support.
  3. Improper use of algorithms: Algorithms should be used with the correct parameters (iterator ranges) to avoid unexpected results or compiler errors. Some algorithms require additional arguments like comparators or functors for custom behavior.
  4. Ignoring container-specific properties: Each container has its unique properties like capacity, size, and iterators. Failing to consider these can lead to inefficient code or runtime errors. Be aware of the specificities of each container class when choosing which one to use for a given task.
  5. Misusing function objects (Functors): Functors should be used correctly with algorithms to achieve the desired behavior. Be aware of the overloaded operators and member functions that can be overridden in functor classes.
  6. ### Common Algorithm Mistakes
  • Using incorrect iterator categories: Ensure that iterators used with algorithms support the required operations, such as reading or writing data.
  • Incorrectly specifying iterator ranges: Make sure to use the correct iterator pair (begin and end) when calling algorithms like sort or find.
  • Improper use of comparators: When sorting containers with custom comparators, ensure that the functor follows the strict weak ordering principle.
  1. ### Common Container Mistakes
  • Ignoring capacity and size: Be aware of the current capacity and size of a container to avoid runtime errors when adding or accessing elements.
  • Misusing container iterators: Iterator invalidation rules may change depending on the container operation, so be mindful of these when traversing containers.
  • Using inappropriate containers: Choose the most suitable container for a given task based on its properties like capacity, efficiency, and support for duplicate values.
  1. ### Common Functor Mistakes
  • Incorrect operator() implementation: Ensure that the operator() function correctly implements the required behavior for custom comparators or manipulators.
  • Improper functor instantiation: When using predefined functors like std::greater, make sure to provide the correct template arguments (T).

Practice Questions

  1. Write a program that uses the list container to store a list of names and sorts them alphabetically using the sort algorithm.
  2. Create a program that counts the frequency of each word in a given string using an unordered_map container.
  3. Implement a custom comparator function object (Functor) for sorting a vector of Student objects based on their average grades.
  4. Write a program that uses the deque container to implement a Last-In-First-Out (LIFO) stack data structure and performs basic stack operations like push, pop, and peek.
  5. Implement a custom iterator for a self-defined SinglyLinkedList class that supports the required iterator operations.
  6. ### Advanced Practice Questions
  • Implement a binary search algorithm using an unordered_map container: Use the find() function to perform a binary search on an unordered_map.
  • Create a custom algorithm for finding the median of a vector: Write a custom algorithm that finds the median of a sorted vector by iterating through the elements and keeping track of the middle element or elements.
  • Implement a custom container class that supports both bidirectional and random access iterators: Design a custom container class (e.g., MyVector) that can be used with both bidirectional and random access iterators, providing the necessary iterator operations like increment, decrement, dereferencing, etc.
  • Create a custom functor for element-wise multiplication of two vectors: Implement a custom functor (e.g., Multiply) that can be used with the std::transform algorithm to perform element-wise multiplication of two vectors.

FAQ

  1. What is the difference between a vector and an array in C++?

A vector is a dynamic array that can grow or shrink as needed, while an array has a fixed size at creation. Vectors offer more flexibility but may have slightly slower access times compared to arrays.

  1. Can I use algorithms with arrays directly in STL?

No, you cannot use algorithms directly with arrays in STL. However, you can convert an array to a vector and then apply the algorithms on the vector. Alternatively, you can adapt the algorithms to work with arrays using pointers and iterators.

  1. What is the purpose of iterators in STL?

Iterators provide a uniform way to traverse different types of containers and access their elements. They allow writing generic algorithms that can work with various container classes, making it easier to manipulate data structures without worrying about their implementation details.

  1. How do I create my own iterator class for a custom data structure?

To create your own iterator class for a custom data structure, you should implement the required iterator operations like operator++, operator--, operator*, and operator==. You may also need to provide a way to construct iterators for your specific data structure.

  1. What are some common pitfalls when using STL algorithms?

Some common pitfalls when using STL algorithms include incorrect iterator usage, forgetting to include necessary headers, improper use of comparators or functors, and ignoring container-specific properties. Be sure to understand the requirements and limitations of each algorithm and choose the appropriate one for your task.

C++ Standard Template Library | C++ | XQA Learn