Skip to content

C++ STL Tutorial

Modern C++: The Standard Template Library (STL)

Section titled “Modern C++: The Standard Template Library (STL)”

Assuming you have a grasp of C++ Templates, let’s dive into the C++ Standard Template Library (STL). The STL is a cornerstone of modern C++ development, providing a powerful collection of template classes and functions. It offers ready-to-use implementations of common algorithms and data structures like vectors (dynamic arrays), lists, queues, maps, and more, saving development time and promoting code reuse.

The STL is built upon three fundamental pillars:

ComponentDescription
ContainersObjects that store collections of other objects (elements). Examples include std::vector, std::list, std::map, std::set. They manage memory automatically.
AlgorithmsFunctions that perform operations on ranges of elements, often within containers. Examples: std::sort, std::find, std::copy, std::accumulate. They are designed to work efficiently with different container types via iterators.
IteratorsObjects that act like generalized pointers, enabling traversal through the elements of a container (or other sequence). They provide a uniform interface for algorithms to access container elements, decoupling algorithms from specific container implementations.

These three components work seamlessly together. For instance, you can use an STL algorithm like std::sort to sort elements in an STL container like std::vector by using iterators provided by the vector to specify the range to be sorted.

Let’s look at std::vector, a dynamic array that automatically manages its size:

#include <iostream>
#include <vector>
#include <string> // Often useful, though not strictly needed for this example
int main() {
// Create a vector to store integers
std::vector<int> vec;
// Display the initial size of vec
std::cout << "Initial vector size = " << vec.size() << std::endl;
// Add 5 values into the vector using push_back
// push_back adds elements to the end
for (int i = 0; i < 5; ++i) {
vec.push_back(i * 10); // Add 0, 10, 20, 30, 40
}
// Display the extended size of vec
std::cout << "Extended vector size = " << vec.size() << std::endl;
// Access values using the subscript operator [] (like arrays)
std::cout << "Accessing values using []:" << std::endl;
for (size_t i = 0; i < vec.size(); ++i) { // Use size_t for indices
std::cout << "value of vec[" << i << "] = " << vec[i] << std::endl;
}
// Access values using a range-based for loop (modern C++)
std::cout << "Accessing values using range-based for loop:" << std::endl;
for (int val : vec) {
std::cout << "Value = " << val << std::endl;
}
// Access values using iterators (explicitly)
std::cout << "Accessing values using iterators:" << std::endl;
// Use 'auto' for type deduction (modern C++)
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << "Value via iterator = " << *it << std::endl;
}
// Using STL algorithms (example: find)
auto it_find = std::find(vec.begin(), vec.end(), 30);
if (it_find != vec.end()) {
std::cout << "Found value 30 at index: " << std::distance(vec.begin(), it_find) << std::endl;
} else {
std::cout << "Value 30 not found." << std::endl;
}
return 0;
}

When the above code is compiled (e.g., g++ your_file.cpp -o program -std=c++11) and executed, it produces a result similar to this:

Initial vector size = 0
Extended vector size = 5
Accessing values using []:
value of vec[0] = 0
value of vec[1] = 10
value of vec[2] = 20
value of vec[3] = 30
value of vec[4] = 40
Accessing values using range-based for loop:
Value = 0
Value = 10
Value = 20
Value = 30
Value = 40
Accessing values using iterators:
Value via iterator = 0
Value via iterator = 10
Value via iterator = 20
Value via iterator = 30
Value via iterator = 40
Found value 30 at index: 3

Key takeaways from the example:

  • #include <vector> is needed to use std::vector.
  • vec.push_back(value) adds an element to the end, resizing if necessary.
  • vec.size() returns the current number of elements.
  • Elements can be accessed using [] like arrays (be careful with bounds).
  • Range-based for loops (for (int val : vec)) provide a concise way to iterate over elements.
  • vec.begin() returns an iterator to the first element.
  • vec.end() returns an iterator past the last element.
  • auto simplifies iterator declarations (auto it = vec.begin();).
  • STL algorithms like std::find operate on iterator ranges.

The STL offers many more containers (std::list, std::map, std::set, std::unordered_map, etc.) and algorithms, forming the backbone of efficient and maintainable C++ code. Exploring these is crucial for advanced C++ programming. You can find comprehensive documentation at sites like cppreference.com.