C++ Iterators
In C++, iterators are objects that allow you to traverse through the elements of a container (such as arrays, vectors, lists, maps, etc.) in a generic way. They provide a unified interface to access elements in different types of containers, enabling you to write code that works with any container type without having to explicitly know the underlying structure.
Iterators are a core part of the C++ Standard Template Library (STL) and play a crucial role in making C++ containers flexible and reusable.
There are several types of iterators in C++, which offer different levels of functionality:
To declare an iterator, use the syntax:
iterator_type<Container>::iterator iterator_name;
Where:
iterator_type<Container>
is the specific iterator type for the container you're working with, such as std::vector<int>::iterator
for a vector of integers.iterator_name
is the name of your iterator.std::vector
Let's look at an example of how to use an iterator with a std::vector
container.
#include <iostream>
#include <vector>
int main() {
// Declare and initialize a vector
std::vector<int> vec = {1, 2, 3, 4, 5};
// Declare an iterator for the vector
std::vector<int>::iterator it;
// Iterate through the vector using the iterator
for (it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " "; // Dereferencing iterator to access element
}
return 0;
}
Output:
1 2 3 4 5
In this example:
vec.begin()
returns an iterator to the first element.vec.end()
returns an iterator that points one position past the last element.*it
to access the element it points to.Iterators support several operations that allow you to traverse and manipulate container elements:
You can dereference an iterator to access the element it points to:
*it // Dereferences the iterator to access the value
You can move the iterator to the next or previous element by using the increment (++
) or decrement (--
) operators:
++it // Move iterator forward (next element)
--it // Move iterator backward (previous element)
You can compare iterators to check if one iterator is equal to or different from another, typically used with begin()
and end()
:
it == vec.end() // Check if iterator has reached the end
it != vec.end() // Check if iterator has not yet reached the end
For random access iterators (like those for std::vector
and std::deque
), you can directly access elements using arithmetic operations like +
or -
.
*(it + 2) // Access the third element from the current position
C++ iterators work with various types of containers. Here's a look at how to use iterators with different container types:
std::list
Unlike std::vector
, std::list
is a doubly linked list and provides bidirectional iterators.
#include <iostream>
#include <list>
int main() {
std::list<int> lst = {10, 20, 30, 40, 50};
std::list<int>::iterator it;
// Iterating through the list using iterator
for (it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
return 0;
}
Output:
10 20 30 40 50
std::map
A std::map
is a sorted associative container, and its iterators allow you to access both the key and the associated value.
#include <iostream>
#include <map>
int main() {
std::map<int, std::string> map = {{1, "One"}, {2, "Two"}, {3, "Three"}};
// Iterate through the map using iterators
for (std::map<int, std::string>::iterator it = map.begin(); it != map.end(); ++it) {
std::cout << it->first << ": " << it->second << std::endl;
}
return 0;
}
Output:
1: One
2: Two
3: Three
In this example, it->first
accesses the key, and it->second
accesses the value.
std::set
std::set
also supports iterators, and iterating through it will give you the elements in sorted order.
#include <iostream>
#include <set>
int main() {
std::set<int> s = {5, 2, 3, 8, 1};
// Using iterators to iterate through set (elements will be in sorted order)
for (std::set<int>::iterator it = s.begin(); it != s.end(); ++it) {
std::cout << *it << " ";
}
return 0;
}
Output:
1 2 3 5 8
To traverse a container in reverse order, use reverse iterators. You can get a reverse iterator using rbegin()
and rend()
.
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// Use reverse iterators to print in reverse order
for (std::vector<int>::reverse_iterator rit = vec.rbegin(); rit != vec.rend(); ++rit) {
std::cout << *rit << " ";
}
return 0;
}
Output:
5 4 3 2 1
You can also use iterators to work with subranges of containers, for example, copying or modifying part of a container.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::vector<int> subVec(3);
// Copy a range of elements from vec to subVec
std::copy(vec.begin(), vec.begin() + 3, subVec.begin());
// Print subVec
for (int i : subVec) {
std::cout << i << " ";
}
return 0;
}
Output:
1 2 3