Iterators are just like pointers used to access the container elements.
<ContainerType> :: iterator; <ContainerType> :: const_iterator;
Iterators can be smart pointers which allow to iterate over the complex data structures. A Container provides its iterator type. Therefore, we can say that the iterators have the common interface with different container type.
The container classes provide two basic member functions that allow to iterate or move through the elements of a container:
Let's see a simple example:
#include <iostream> #include<iterator> #include<vector> using namespace std; int main() { std::vector<int> v{1,2,3,4,5}; vector<int>::iterator itr; for(itr=v.begin();itr!=v.end();itr++) { std::cout << *itr <<" "; } return 0; }
An iterator can be categorized in the following ways:
An input iterator is an iterator used to access the elements from the container, but it does not modify the value of a container.
Operators used for an input iterator are
An output iterator is an iterator used to modify the value of a container, but it does not read the value from a container. Therefore, we can say that an output iterator is a write-only iterator.
Operators used for an output iterator are
A forward iterator is an iterator used to read and write to a container. It is a multi-pass iterator.
Operators used for a Forward iterator are
A bidirectional iterator is an iterator supports all the features of a forward iterator plus it adds one more feature, i.e., decrement operator(--). We can move backward by decrementing an iterator.
Operators used for a Bidirectional iterator are
A Random Access iterator is an iterator provides random access of an element at an arbitrary location. It has all the features of a bidirectional iterator plus it adds one more feature, i.e., pointer addition and pointer subtraction to provide random access to an element.
Iterator categories | Provider |
---|---|
Input iterator | istream |
Output iterator | ostream |
Forward iterator | |
Bidirectional iterator | List, set, multiset, map, multimap |
Random access iterator | Vector, deque, array |
Iterator | Access method | Direction of movement | I/O capability |
---|---|---|---|
Input | Linear | Forward only | Read-only |
Output | Linear | Forward only | Write-only |
Forward | Linear | Forward only | Read/Write |
Bidirectional | Linear | Forward & backward | Read/Write |
Random | Random | Forward & backward | Read/Write |
Following are the advantages of an iterator
Let's see a simple example
#include <iostream> #include<vector> #include<iterator> using namespace std; int main() { vector<int> v{1,2,3,4,5}; vector<int>::iterator itr; for(int i=0;i<5;i++) // Traversal without using an iterator. { cout<<v[i]<<" "; } cout<<'\n'; for(itr=v.begin();itr!=v.end();itr++) // Traversal by using an iterator. { cout<<*itr<<" "; } v.push_back(10); cout<<'\n'; for(int i=0;i<6;i++) { cout<<v[i]<<" "; } cout<<'\n'; for(itr=v.begin();itr!=v.end();itr++) { cout<<*itr<<" "; } return 0; }
In the above example, we observe that if we traverse the elements of a vector without using an iterator, then we need to keep track of the number of elements added in the container.
#include <iostream> #include<vector> #include<iterator> using namespace std; int main() { vector<int> v{1,2,3,4,5}; // vector declaration vector<int>::iterator itr; v.insert(v.begin()+1,10); for(itr=v.begin();itr!=v.end();itr++) { cout<<*itr<<" "; } return 0; }
In the above example, we insert a new element at the second position by using insert() function and all other elements are shifted by one.
The most important difference between the Random access iterator and other iterators is that random access iterator requires '1' step to access an element while other iterators require 'n' steps.