<iterator>
The <iterator>
header is part of the C++ Standard Library that provides a set of classes and functions for working with iterators. Iterators are a generalization of pointers, used to access elements in containers or sequences. This header defines several iterator categories, iterator traits, and utility functions that facilitate the implementation and use of iterators in C++ programs.
#include <iostream>
#include <vector>
#include <list>
#include <iterator>
template <typename Iterator>
void print_iterator_category(const Iterator& it) {
if (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::random_access_iterator_tag>)
std::cout << "Random Access Iterator" << std::endl;
else if (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::bidirectional_iterator_tag>)
std::cout << "Bidirectional Iterator" << std::endl;
else if (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::forward_iterator_tag>)
std::cout << "Forward Iterator" << std::endl;
else if (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::input_iterator_tag>)
std::cout << "Input Iterator" << std::endl;
else if (std::is_same_v<typename std::iterator_traits<Iterator>::iterator_category, std::output_iterator_tag>)
std::cout << "Output Iterator" << std::endl;
}
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
std::list<int> lst = {1, 2, 3, 4, 5};
std::cout << "Vector iterator category: ";
print_iterator_category(vec.begin());
std::cout << "List iterator category: ";
print_iterator_category(lst.begin());
return 0;
}
iterator_traits
to determine and print the category of an iterator.std::is_same_v
is used to compare iterator categories.std::vector
(random access) and std::list
(bidirectional).#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::cout << "Forward iteration: ";
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
std::cout << "Reverse iteration: ";
for (auto rit = numbers.rbegin(); rit != numbers.rend(); ++rit) {
std::cout << *rit << " ";
}
std::cout << std::endl;
// Using reverse iterators with algorithms
std::cout << "Reverse sorted: ";
std::sort(numbers.rbegin(), numbers.rend());
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
rbegin()
and rend()
return reverse iterators.std::sort
.#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <sstream>
int main() {
// Reading from standard input
std::cout << "Enter numbers (Ctrl+D to end):" << std::endl;
// Use { } to interpret expression as initializers
std::vector<int> numbers{std::istream_iterator<int>(std::cin), std::istream_iterator<int>()};
// Writing to standard output
std::cout << "You entered: ";
std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Using stringstream with stream iterators
std::stringstream ss("10 20 30 40 50");
// Use { } to interpret expression as initializers
std::vector<int> more_numbers{std::istream_iterator<int>(ss), std::istream_iterator<int>()};
std::cout << "Numbers from stringstream: ";
std::copy(more_numbers.begin(), more_numbers.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
istream_iterator
is used to read integers from standard input and a stringstream.ostream_iterator
is used to write integers to standard output.#include <iostream>
#include <iterator>
class Fibonacci {
private:
int current;
int next;
public:
class iterator {
private:
int current;
int next;
public:
using iterator_category = std::input_iterator_tag;
using value_type = int;
using difference_type = std::ptrdiff_t;
using pointer = const int*;
using reference = const int&;
iterator(int current = 0, int next = 1) : current(current), next(next) {}
int operator*() const { return current; }
iterator& operator++() {
int temp = current;
current = next;
next = temp + next;
return *this;
}
iterator operator++(int) {
iterator temp = *this;
++(*this);
return temp;
}
bool operator==(const iterator& other) const { return current == other.current; }
bool operator!=(const iterator& other) const { return !(*this == other); }
};
Fibonacci() : current(0), next(1) {}
iterator begin() { return iterator(); }
iterator end() { return iterator(89); } // Arbitrary end point
};
int main() {
Fibonacci fib;
std::cout << "First 10 Fibonacci numbers: ";
int count = 0;
for (auto i : fib) {
if (count++ == 10) break;
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// Using back_insert_iterator
std::vector<int> vec2;
std::copy(vec.begin(), vec.end(), std::back_inserter(vec2));
std::cout << "Vector after back insertion: ";
for (int n : vec2) std::cout << n << " ";
std::cout << std::endl;
// Using front_insert_iterator
std::vector<int> vec3;
std::copy(vec.begin(), vec.end(), std::front_inserter(vec3));
std::cout << "Vector after front insertion: ";
for (int n : vec3) std::cout << n << " ";
std::cout << std::endl;
// Using insert_iterator
std::vector<int> vec4 = {10, 20, 30};
std::copy(vec.begin(), vec.end(), std::inserter(vec4, vec4.begin() + 2));
std::cout << "Vector after insert: ";
for (int n : vec4) std::cout << n << " ";
std::cout << std::endl;
return 0;
}
back_inserter
creates an iterator that uses push_back
to add elements to the end of a container.front_inserter
creates an iterator that uses push_front
to add elements to the beginning of a container.inserter
creates an iterator that inserts elements at a specified position in the container.Iterator Invalidation: Be aware that certain operations on containers can invalidate iterators.
Performance: Different iterator categories have different performance characteristics. Random access iterators generally offer the best performance for algorithms.
Const Correctness: Use const_iterator
when you don't need to modify the elements being iterated over.
Custom Iterators: When implementing custom iterators, ensure they conform to the expected behavior of their category.
C++20 Concepts: With C++20, iterator concepts provide a more refined way to specify iterator requirements.
The <iterator>
header in C++ provides essential tools for working with iterators:
Iterators are a fundamental concept in C++, bridging the gap between algorithms and containers. They provide a uniform way to access elements in different types of containers, enabling the writing of generic, reusable code. The <iterator>
header is crucial for leveraging the full power of the STL and for implementing efficient, flexible data structures and algorithms.
Understanding and effectively using the facilities provided by <iterator>
is essential for writing idiomatic, efficient C++ code, especially when working with the STL or implementing custom containers and algorithms. It's a key component in achieving the abstraction and genericity that C++ is known for in systems and application programming.