What Are Iterators in C++?

Iterators are one of the four pillars of the Standard Template Library or STL in C++. An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent.

Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container. They allow you to iterate over the container, access and assign the values, and run different operators over them, to get the desired result.

Iterators in C++ are classified into 5 major categories based on their functionality. The following 5 iterators are explored in-depth, further in this article: 

  • Input iterator
  • Output iterator
  • Forward iterator
  • Bidirectional iterator
  • Random access iterator

Use of Iterators in C++

An iterator in C++ serves the following major purposes:

  • The primary objective of an iterator is to access the STL container elements and perform certain operations on them. 
  • The internal structure of a container does not matter, since the iterators provide common usage for all of them.
  • Iterator algorithms are not dependent on the container type.
  • An iterator can be used to iterate over the container elements. It can also provide access to those elements to modify their values.
  • Iterators follow a generic approach for STL container classes. This way, the programmers don’t need to learn about different iterators for different containers.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Syntax of Defining Iterators

<Container_Type> :: iterator;  

<Container_Type> :: const_iterator;  

Parameters used in the above syntax:

  • Container_Type: This parameter is the type of container for which the iterator is declared.

All STL containers do not support all 5 types of iterators. For instance, random-access iterators are supported by the container “vector”, whereas bidirectional iterators are supported by the container “list”. 

The following table contains STL containers and the iterators that are supported by them in C++:

STL CONTAINER

ITERATOR SUPPORTED

Vector 

Random-Access

List 

Bidirectional

Dequeue

Random-Access

Map

Bidirectional

Multimap

Bidirectional

Set

Bidirectional

Multiset

Bidirectional

Stack

Does not support any iterator

Queue

Does not support any iterator

Priority-Queue

Does not support any iterator

Difference Between Iterators and Pointers

Although pointers and iterators seem alike at first glance, there are many significant differences between them which you need to understand. 

Pointers:

A pointer is a variable that stores the memory address of the variable it is pointing to. Like a normal variable, a pointer also has a data type that is the same as the data type of the variable whose memory it is storing. The pointer helps to provide large information to the functions by just passing the memory address of the object.

Syntax to declare a pointer in C++:

data_type* pointer_name 

The following program illustrates the concept of pointers in C++:

#include <iostream> 

using namespace std;

int main() 

{

    // initialize a variable myVar

    int myVar = 10;      

    // initialize a pointer ptr

    // pointing to myVar             

    int* ptr = &myVar;  

    // printing myVar will display 10

    cout << "Value stored in myVar: " << myVar;

    cout << "\n"; 

    // printing *ptr will also display 10

    cout << "Dereferenced pointer pointing to myVar: " << *ptr;

    cout << "\n";

    // update the value of myVar

    myVar++;  

    // now *ptr will print 11, since myVar has been updated

    cout << "Dereferenced pointer pointing to myVar after updating myVar: ";

    cout << *ptr;

    cout << "\n\n";

    return 0; 

Iterator_in_C_Plus_Plus_1

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Iterators:

Iterators are used to point to the memory addresses of the STL containers. Apart from that, an iterator is also used to iterate over the data structures. It can access or assign values that a pointer is unable to do. 

Pointers in C++ can also point to functions, whereas the iterators just serve the purpose of performing operations on the STL containers.

Syntax to declare an iterator  in C++:

type_container :: iterator itr_name 

The following program illustrates the concept of iterators in C++: 

#include <iostream>

#include <vector>

using namespace std;

int main()

{

    // initialize a vector

    vector<int> v1 = { 10, 20, 30, 40 }; 

    // declare an iterator

    vector<int>::iterator itr;

    // access vector elements without iterator

    cout << "Traversing without iterator : ";

    for (int j = 0; j < 4; ++j) {

        cout << v1[j] << " ";

    }

    cout << "\n";

    // access vector elements using an iterator

    cout << "Traversing using iterator ";

    for (itr = v1.begin(); itr != v1.end(); ++itr) {

        cout << *itr << " ";

    }

    cout << "\n\n";

    // insert an element into the vector

    v1.push_back(50);

    // access vector elements without iterator

    cout << "Traversing without iterator : ";

    for (int j = 0; j < 5; ++j) {

        cout << v1[j] << " ";

    }

    cout << "\n";

    // access vector elements using an iterator

    cout << "Traversing using iterator ";

    for (itr = v1.begin(); itr != v1.end(); ++itr) {

        cout << *itr << " ";

    }

    cout << "\n\n";

    return 0;

}

Iterator_in_C_Plus_Plus_2

Categories of Iterators

As earlier discussed, there are 5 main types of iterators in C++ STL. In this section, you are going to see all these 5 iterators in detail. These 5 iterators are:

1. Input Iterators in C++

The input iterator is the simplest and least used iterator among the five main iterators of C++. It sequentially uses this iterator for input operations. In other words, you can say that it is used to read the values from the container. It is a one-way iterator. Once you have read a value, you are only allowed to increment the iterator. You can not decrement the input iterator in any way.

Salient Features

The input iterator in C++ has the following salient features: 

  • Equality and Inequality operator: You can compare the equality of two input iterators. Two iterators are said to be equal if both of them are pointing towards the same location. Otherwise, they are considered unequal.

In the expression shown below, consider it1 and it2 as two input iterators:

it1 == it2  //Using equality operator

it1 != it2  //Using inequality operator

  • Usability: Input iterators are one-way iterators. This means that you can use them to iterate only in one direction at a time. These iterators work on a “single-pass algorithm”. 
  • Dereferencing: Dereferencing is used to access the data whose address is being pointed to by a pointer. The asterisk (*) is used alongside the pointer variable name for dereferencing a pointer variable.

In the expression shown below, consider it as an input iterator:

*it     // Dereferencing it using the asterisk(*)

  • Incrementable: Since input iterators are one-way iterators, you can increment them in the forward direction. These iterators can be incremented either in a pre-increment manner or post-increment manner.

In the expression shown below, consider it as an input iterator:

it++   // Using post increment operator

++it   // Using pre increment operator

  • Swappable: The values of the two input iterators that are pointing to different positions can be easily swapped or exchanged with each other.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Limitations

The following are some of the major limitations of the input iterators in C++:

  • Input iterators are read-only. They can only read the data of the location to which the pointer points, they can not be used to assign the values.
  • As mentioned earlier, these iterators are unidirectional. They can only move in a forward direction i.e., they can only be incremented. You can not decrement them.
  • You can not use these iterators in a multi-pass algorithm where you have to move in both directions inside a container.
  • Except for equality and inequality operators, you can not implement any other relational operator on these iterators.
  • Like relational operators, you cannot implement arithmetic operators on the input iterators.

The following example will illustrate the input iterator in C++:

#include<bits/stdc++.h>

using namespace std;  

int main()  

{  

    // initialize a vector

    vector<int> v{1, 2, 3, 4, 5};

    // declare iterators  

    vector<int>::iterator it1, it2, temp; 

    // inititalize the iterators

    it1 = v.begin();   // will point to the first element, i.e. 1

    it2 = v.end() - 1;  // will point to the last element, i.e. 5

    // dereference and print iterators before swapping them

    cout << "Before Swapping" << endl;

    cout << "Dereferenced iterator 1: " << *it1 << " " ;

    cout << "\n";  

    cout << "Dereferenced iterator 2: " << *it2;

    cout << "\n\n";

    // swap the iterators

    temp = it1;  

    it1 = it2;  

    it2 = temp;   

    // dereference and print iterators after swapping them

    cout << "Before Swapping" << endl;

    cout << "Dereferenced iterator 1: " << *it1 << " " ;

    cout << "\n";  

    cout << "Dereferenced iterator 2: " << *it2;

    cout << "\n\n";

    return 0;  

}  

Iterator_in_C_Plus_Plus_3

2. Output Iterators in C++

Output iterators serve exactly the opposite purpose as the input iterators. This iterator is sequentially used for output operations. In other words, you can say that it is used to assign the values. But it can not access the values. It is complementary to the input iterators where you can access the values, but can not assign them. Like the input iterator, it is a one-way iterator. Once you have assigned a value, you are only allowed to increment the iterator, and you can not decrement the output iterator in any way.

Salient Features

The output iterator in C++ has the following salient features: 

  • Equality and Inequality operator: Just like the input iterators, you can compare the equality of two output iterators. Two iterators are said to be equal if both of them are pointing towards the same location. Otherwise, they are considered unequal.

In the expression shown below, consider it1 and it2 as two output iterators:

it1 == it2  // Using equality operator

it1 != it2  // Using inequality operator

  • Usability: Output iterators also work with single-pass algorithms where you can visit an element only once at most. You can assign the value only once.
  • Dereferencing: You can dereference an output iterator as an lvalue to get the position for storing the value. The method of dereferencing is the same as for the input iterators.

In the expression shown below, consider it as an output iterator:

*it   // Dereferencing it using the asterisk(*)

  • Incrementable: Just like input iterators, output iterators are one-way iterators too, and you can increment them in the forward direction. These iterators can be incremented either in a pre-increment manner or post-increment manner.

In the expression shown below, consider it as an output iterator:

it++   // Using post increment operator

++it   // Using pre increment operator

  • Swappable: The value of the two output iterators that are pointing to different positions can be easily swapped or exchanged with each other.

Limitations

The following are some of the major limitations of the output iterators in C++:

  • You can not access the values using output iterators. These iterators can only be used to assign the values.
  • As mentioned earlier, these iterators are unidirectional. They only move in a forward direction i.e., they can only be incremented. You can not decrement them.
  • You can not use these iterators in a multi-pass algorithm where you have to move in both directions inside a container.
  • Just like in input iterators, except for equality and inequality operators, you can not implement any other relational operator on output iterators.
  • Like relational operators, arithmetic operators can not be implemented on the output iterators.

The following example illustrates the output iterator in C++:

#include<bits/stdc++.h>

using namespace std;

int main () {

    // initialize 2 vectors

   vector<int> v1, v2;

   // add elements into the vectors

   for (int i = 1; i <= 10; i++) { 

      v1.push_back(i);

      v2.push_back(i + 2);

   }

   // initialize an iterator itr pointing to 

   // the first element in vector v1

   vector<int>::iterator itr = v1.begin(); 

    // copy elements of v2 vector to v1 vector at 

    // the beginning

   copy (v2.begin(), v2.end(), inserter(v1, itr));

   // print the elements of the vector v1

   cout<<"Elements of vector v1 after copying elements of v2 are :"<< endl;

   for ( itr = v1.begin(); itr!= v1.end(); ++itr ) 

   {

      cout << " " << *itr;

   }

      cout << "\n\n";

}

Iterator_in_C_Plus_Plus_4

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

3. Forward Iterators in C++

Forward iterators serve the purpose of both the input and output iterators. That’s why these iterators are said to be the combination of input and output operators. You can access the values (functionality of input iterators) as well as assign the values (functionality of output iterators). As the name suggests, these iterators are one-way iterators. You can only traverse in the forward direction. Also, Bidirectional and Random Access iterators are considered valid forward iterators.

Salient Features

The forward iterator in C++ has the following salient features: 

  • Equality and Inequality operator: Just like the other two iterators mentioned above, you can compare the equality of two output iterators. Two iterators are said to be equal if both of them are pointing towards the same location. Otherwise, they are considered unequal.

In the expression shown below, consider it1 and it2 as two forward iterators:

it1 == it2  // Using equality operator

it1 != it2  // Using inequality operator

  • Usability: Forward iterator is the only iterator category that is used by every STL container class. It is the only iterator among the 5 types of iterators that provides the functionality of the simplest kind of loop through a container.
  • Dereferencing: Since input iterators are dereferenced as an rvalue and output iterators are dereferenced as an lvalue, and forward iterators are the combination of these iterators, you can use both rvalue and lvalue.
  • Incrementable: Forward iterators unidirectional iterators and you can increment them in the forward direction. These iterators can be incremented either in a pre-increment manner or post-increment manner.

In the expression shown below, consider it as a forward iterator:

it++   // Using post increment operator

++it   // Using pre increment operator

  • Swappable: The value of the two forward iterators that are pointing to different positions can be easily swapped or exchanged with each other.

Limitations

The following are some of the major limitations of the forward iterators in C++:

  • The offset dereference operator ([]) is not supported by the forward iterators. So you can not use the offset operator to dereference a forward iterator.
  • As mentioned earlier, these iterators are unidirectional. They only move in a forward direction i.e., they can only be incremented. You can not decrement them.
  • Just like in input and output iterators, except for equality and inequality operators, you can not implement any other relational operator on the forward iterators.
  • Like relational operators, arithmetic operators can not be implemented on the forward iterators.

The following example will illustrate the forward iterator in C++:

#include<bits/stdc++.h>

using namespace std;  

template<class FIterator>                               

void forwardIterator(FIterator start, FIterator end)   

{  

     while(start != end)  

     {  

         // dereference the iterator

         // to print its value

         cout << *start << " ";  

         start++;  

     }  

}  

int main()  

{  

  // declare a vector

  vector<int> v1;  

    // add elements to the vector v1

  for(int i = 1; i <= 10; i++)  

  {  

      v1.push_back(i + 2);  

  }  

  // call the forward Iterator function

  // pass the vector v1

  forwardIterator(v1.begin(),v1.end());  

  cout << "\n\n";

  return 0;  

}

Iterator_in_C_Plus_Plus_5

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

4. Bidirectional Iterators in C++

Bidirectional iterators can iterate in either direction. They are considered as the forward iterators with two decrement operators because they offer the same functionality as the forward iterators, except that they can move in both directions. The containers like list, set, and multimap supports bidirectional iterators. The random access iterators are also considered valid bidirectional iterators. 

Salient Features

The bidirectional iterator in C++ has the following salient features: 

  • Equality and Inequality operator: Two bidirectional iterators can be compared as to whether they are equal or not. Two iterators are said to be equal if both of them are pointing towards the same location. Otherwise, they are considered unequal.

In the expression shown below, consider it1 and it2 as two bidirectional iterators:

it1 == it2  //Using equality operator

it1 != it2  //Using inequality operator

  • Usability: Forward iterators are used for multi-pass algorithms (the algorithms that may need the read and write operations multiple times). Therefore, bidirectional operators can also be used for multi-pass algorithms.
  • Dereferencing: Since input iterators are dereferenced as rvalue and output iterators are dereferenced as an lvalue and forward iterators are the combination of these iterators, you can use both rvalue and lvalue. So, bidirectional iterators can also be used for the same purpose.
  • Incrementable/Decrementable: Bidirectional iterators are valid forward iterators and forward iterators are unidirectional. But bidirectional iterators can move in either way. You can increment your iterator pointer as well as decrement it. That is why they are named bidirectional.

In the expression shown below, consider it as a bidirectional iterator:

//********Incrementing the iterator********//

it++   // Using post increment operator

++it   // Using pre increment operator

//********Decrementing the iterator********//

it--   // Using post decrement operator

--it   // Using pre decrement operator

  • Swappable: The value of the two bidirectional iterators that are pointing to different positions can be easily swapped or exchanged with each other.

Limitations

The following are some of the major limitations of the bidirectional iterators in C++:

  • The offset dereference operator ([]) is not supported by the bidirectional iterators. You can not use the offset operator to dereference a bidirectional iterator.
  • Just like in the forward iterators, except for equality and inequality operators, you can not implement any other relational operator on the bidirectional iterators.
  • Like relational operators, arithmetic operators can not be implemented on the bidirectional iterators.

The following example will illustrate the bidirectional iterator in C++:

#include<bits/stdc++.h>

using namespace std;  

int main()  

{  

    // initialize a vector

   vector<int> v1{10, 20, 30, 40, 50, 60}; 

    // initialize an iterator i1

   vector<int> ::iterator i1;  

    // initialize a reverse iterator rITr

   vector<int> :: reverse_iterator rItr;

   // dereference and print i1 

   // to print values in original order

   cout << "Values in original order: " << "\n";

   for(i1 = v1.begin(); i1 != v1.end(); i1++)  

   {  

       cout << *i1 << " ";  

   }  

   cout << "\n\n";  

   // dereference and print rItr 

   // to print values in reverse order

   cout << "Values in reverse order: " << "\n";

   for(rItr = v1.rbegin(); rItr != v1.rend(); rItr++)  

   {  

       cout << *rItr << " ";  

   }  

   cout << "\n\n";

    return 0;  

}  

Iterator_in_C_Plus_Plus_6

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

5. Random-Access Iterators in C++

Random Access iterators are considered to be the most completed iterators among all the five iterators. These iterators are also stated as bidirectional iterators with random access.

Salient Features

The random-access iterator in C++ has the following salient features: 

  • Equality and Inequality operator: Two random access iterators can be compared to see whether they are equal or not. Two iterators are said to be equal if both of them are pointing towards the same location. Otherwise, they are considered unequal.

In the expression shown below, consider it1 and it2 as two random-access iterators:

it1 == it2  //Using equality operator

it1 != it2  //Using inequality operator

  • Usability: Just like bidirectional iterators, random access iterators can also be used in multi-pass algorithms.
  • Dereferencing: Bidirectional iterators are dereferenced as rvalue as well as an lvalue. Therefore, random access iterators can also be used for the same purpose.
  • Incremental/Decremental: Random access iterators can be incremented as well as decremented, as they are multi-directional.

In the expression shown below, consider it as a random access iterator:

//********Incrementing the iterator********//

it++   // Using post increment operator

++it   // Using pre increment operator

//********Decrementing the iterator********//

it--   // Using post decrement operator

--it   // Using pre decrement operator

  • Swappable: The value of the two random-access iterators that are pointing to different positions can be easily swapped or exchanged with each other.

  • Relational Operators: Unlike other iterators, random access supports all the relational operators.

  • Arithmetic Operators: Just like relational operators, arithmetic operators can be implemented on the random access iterators.

  • Offset dereference operator: The offset dereference operator ([]) is supported by the random access iterators. You can use the offset operator to dereference a random-access iterator.

The following example illustrates the random-access iterator in C++:

#include<bits/stdc++.h>

using namespace std;

int main()

{

    // initialize a vector

    vector<int>vec1 = {10, 20, 30, 40, 50, 60};

    // declare iterator i1

    vector<int>::iterator i1;

    // declare iterator i2

    vector<int>::iterator i2;

    // initialize i1 and point it to 

    // the first element of the vector

    i1 = vec1.begin();

    // initialize i2 and point it to 

    // the last element of the vector

    i2 = vec1.end();

    // compare i1 and i2 using the 

    // relational operator

    if ( i1 < i2)

    {

        cout << "Iterator i2 is greater than iterator i1.";

    }

    // computing the distance using 

    // the arithmetic operator

    int difference = i2 - i1; 

    cout << "\nThe difference between i1 and i2 = " << difference;

    cout << "\n\n";

    return 0;

}

Iterator_in_C_Plus_Plus_7

Operations of Iterators

1. begin():

The begin() function returns a pointer pointing to the first element of the container. This pointer can point in either direction of the container and hence it is bidirectional.

Syntax

begin()

2. end():

The end() method returns a pointer pointing to the element that comes after the last element of the container. This element is not real, it is a virtual element that contains the address of the last element.

Syntax

end()

The following program illustrates the begin() and end() operations of iterators:

#include<iostream> 

#include<iterator> 

#include<vector> 

using namespace std; 

int main() 

    // initialize a vector

    vector<int> myVector = { 100, 200, 300, 400, 500 }; 

    // declare an iterator

    vector<int>::iterator itr;       

    // traverse the vector using the begin() and end() 

    cout << "The vector contains these elements: "; 

    // print the elements of the vector

    for (itr = myVector.begin(); itr < myVector.end(); itr++) {

        cout << *itr << " "; 

    }

    cout << "\n\n";      

    return 0;     

}

Iterator_in_C_Plus_Plus_8

3. advance():

The advance() method is used to increment the iterator from its current position. It takes an integer as its argument. The advance() method increments the pointer up to that integer position. 

Syntax

advance(iterator i ,int distance)

The following program illustrates the advance() operation of iterators:

#include<iostream> 

#include<iterator>  

#include<vector>  

using namespace std; 

int main() 

    // initialize a vector

    vector<int> myVect = { 100, 200, 300, 400, 500 }; 

    // declare an iterator 

    vector<int>::iterator itr;

    // initialize the iterator

    itr = myVect.begin(); 

    // print the original value to 

    // which the iterator is pointing

    cout << "The iterator originally points to: ";

    cout << *itr << " ";

    cout << "\n\n";

    // update the iterator by incrementing it

    // by a distance of 2

    // using advance()

    advance(itr,2);     // iterator now points to 300

    // print the current value to which the 

    // iterator is pointing 

    cout << "The iterator now points to : "; 

    cout << *itr << " "; 

    cout << "\n\n";

    return 0;       

Iterator_in_C_Plus_Plus_9

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

4. next():

The next() method gives an iterator in return that points to the element you get after incrementing the iterator pointer from the current element. 

Syntax

next(iterator i ,int n)

5. prev():

The prev() method is just the opposite of the next() method. It returns an iterator pointer that points to the element that you get after decrementing the iterator from the current element.

Syntax

prev(iterator i, int n)

The following program illustrates the next() and the prev() operation of iterators:

#include<iostream> 

#include<iterator>

#include<vector>

using namespace std; 

int main() 

    // initialize a vector

    vector<int> myVect = { 100, 200, 300, 400, 500 }; 

    // declare iterators for the vector

    vector<int>::iterator i1 = myVect.begin(); 

    vector<int>::iterator i2 = myVect.end(); 

    // store the pointer returned by next()

    // after incrementing i1 by 3

    auto nextptr = next(i1, 3); 

    // store the pointer returned by prev()

    // after decrementing i2 by 3

    auto prevptr = prev(i2, 3); 

    // Displaying iterator position 

    // print the value of the new iterator returned by next()

    cout << "The new pointer after using next() now points to : "; 

    cout << "\n";

    cout << *nextptr << " "; 

    cout << "\n\n"; 

    // Displaying iterator position 

    // print the value of the new iterator returned by prev()

    cout << "The new pointer after using prev() now points to : "; 

    cout << "\n";

    cout << *prevptr << " "; 

    cout << "\n\n"; 

    return 0;  

}

Iterator_in_C_Plus_Plus_10

6. inserter():

The inserter() method is a special type of iterator method. It is used to insert elements at a specified position in a container. If there is already an element at the specified position, then it can also overwrite the elements in the container to insert the new elements.

Syntax

inserter (Container & x, Iterator it)

The following program illustrates the inserter() operation of iterators:

#include<bits/stdc++.h>

using namespace std;

int main () {

    // initialize 2 vectors

   vector<int> myVect1, myVect2;

   // add elements into the vectors

   for (int i = 1; i <= 5; i++) { 

      myVect1.push_back(i);

      myVect2.push_back(i + 4);

   }

   // initialize an iterator itr pointing to 

   // the first element in vector myVect1

   vector<int>::iterator itr = myVect1.begin(); 

    // copy elements of myVect2 vector to myVect1 vector at 

    // the beginning

   copy (myVect2.begin(), myVect2.end(), inserter(myVect1, itr));

   // print the elements of the vector myVect1

   cout<<"Elements of vector myVect1 after copying elements of myVect2 are :"<< endl;

   for ( itr = myVect1.begin(); itr!= myVect1.end(); ++itr ) 

   {

      cout << " " << *itr;

   }

      cout << "\n\n";

}

Iterator_in_C_Plus_Plus_11

Benefits of Iterators

Iterators prove to be highly beneficial in certain fields. Some of these benefits are listed below:

  • Convenience in programming: Iterators provide you with ease and convenience while writing the code. For instance, while using iterators, you do not have to worry about the size of the container. You can easily iterate through the container and get the last element using the end() method. You can even alter the container elements without shifting or doing all the labor.

#include <iostream>

#include <vector>

using namespace std;

int main()

{

    // initialize a vector

    vector<char> v1 = {'a', 'b', 'c', 'd' };

    // declare an iterator

    vector<char>::iterator itr;

    // access vector elements without iterator

    cout << "Traversing without iterator : ";

    for (int j = 0; j < 4; ++j) {

        cout << v1[j] << " ";

    }

    cout << "\n";

    // access vector elements using an iterator

    cout << "Traversing using iterator ";

    for (itr = v1.begin(); itr != v1.end(); ++itr) {

        cout << *itr << " ";

    }

    cout << "\n\n";

    // insert an element into the vector

    v1.push_back('e');

    // access vector elements without iterator

    cout << "Traversing without iterator : ";

    for (int j = 0; j < 5; ++j) {

        cout << v1[j] << " ";

    }

    cout << "\n";

    // access vector elements using an iterator

    cout << "Traversing using iterator ";

    for (itr = v1.begin(); itr != v1.end(); ++itr) {

        cout << *itr << " ";

    }

    cout << "\n\n";

    return 0;

}

Iterator_in_C_Plus_Plus_12

In the code mentioned above, you did not store or calculate the initial size of the container. You simply iterated over the container with the help of an iterator. Then you added an element to the container. This time, you did not calculate the size either. 

You simply iterated over the container. In both cases, you used the same loop and therefore the iterator eased out your work.

  • Code Reusability: Now, consider the above code. If you want to change the vector into a list without changing the code, this would not be possible without an iterator. But since you are using an iterator here, you can just change the declaration of the vector into a list and it will work fine. In this way, you can reuse your code.

  • Dynamic Processing: With the help of iterators, you can dynamically allocate as well as delete the memory. This dynamic processing of containers prevents the wastage of memory. And you can easily alter the size of the containers according to your needs and requirements.

#include <iostream>

#include <vector>

using namespace std;

int main()

{

// initialize a vector

vector<int> v = { 10, 20, 30 };

// declare an iterator

vector<int>::iterator i;

// add elements into vector using the iterator

for (i = v.begin(); i != v.end(); ++i) {

    if (i == v.begin()) {         

        // add 100 at the beginning

        i = v.insert(i, 100);

    }

}

// vect -> 100 10 20 30

// delete an element using the iterator

for (i = v.begin(); i != v.end(); ++i) {

    if (i == v.begin() + 1) {

        // delete 2nd element, i.e. at index 1

        i = v.erase(i);

    }

}

cout << "Vector after performing all operations: ";

cout << "\n";

// vect -> 100 20 30

// Traversing the vector using the iterator

for (i = v.begin(); i != v.end(); ++i) {

    cout << *i << " ";

}

cout << "\n\n";

return 0;

}

Iterator_in_C_Plus_Plus_13

In the code mentioned above, it is clearly shown how you can dynamically add and remove elements from a container with the help of iterators. However, if you try to achieve this dynamic processing of containers without iterators, it would be very laborious, as you have to shift the elements every time.

Disadvantages of Iterators

In the above section, you saw how beneficial iterators are. But there are some drawbacks of using iterators too. Some of these disadvantages are mentioned below:

  • Iterators do not allow you to handle two data structures simultaneously, especially when the data of the first data structure decides your location in the other one.
  • You can not go back while iterating through a container, due to the working process of iterators.
  • The structure of the STL container cannot be updated while traversing it if you are using an iterator to iterate over it.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Providers of Iterators

The following table represents iterators along with their provider containers.

ITERATOR

PROVIDER

Input Iterator

istream

Output Iterator

ostream

Forward iterator

-

Bidirectional iterator

List, set, map, multimap, multiset

Random access iterator

Vector, array, deque

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Iterators and Their Characteristics

Iterators have the characteristics to access, read, write, and iterate over the container elements. However, not all iterators possess all characteristics. The following table represents the iterators along with the characteristics possessed by them.

ITERATORS

CHARACTERISTICS

ACCESS

READ

WRITE

ITERATE

Input

->

= *i

++

Output

*i=

++

Forward

->

= *i

*i=

++

Bidirectional

= *i

*i=

++, - -

Random Access

->, [ ]

= *i

*i=

++, - -

Difference Between Random Access Iterator and Other Iterators

A Random Access iterator differs from the other iterators significantly and also overcomes some limitations faced with other iterators. The key differences between the random access iterator and the other iterators are discussed below:

OTHER ITERATORS

RANDOM ACCESS ITERATORS

Input

Input iterators are only accessible. They can only read the data of the location to which the pointer points, they can not be used to assign the values.

Random Access iterators can be used to assign the values.

Output

You can not access the values using output iterators. These iterators can only be used to assign the values.

You can access the values of the container using this iterator.

Forward

Forward iterators are unidirectional. They only move in a forward direction i.e., they can only be incremented. You cannot decrement them.

These iterators are bidirectional. You can move forward as well as backward using these iterators.

Bidirectional

The offset dereference operator ([]) is not supported by the bidirectional iterators. You can not use the offset operator to dereference a bidirectional iterator.

These iterators support the use of the offset dereferences operator for dereferencing the variables.

Except for equality and inequality operators, you can not implement any other relational operators on the bidirectional iterators.

You can implement every relational operator on random access iterators.

Like relational operators, arithmetic operators can not be implemented on the bidirectional iterators.

Unlike bidirectional operators, you can implement relational operators on these iterators.

Wrapping Up!

In this article, you have learned a lot about Iterators in C++. This article talked about different categories of iterators as well as their use cases. You then dived deep into the advantages as well as disadvantages of the iterators. You also explored how each iterator is beneficial in its own way.

To better understand the entire C++ programming language, you can go through our guide on C++ Programming for Beginners

Don’t just stop here. To learn Full-stack Development and to give yourself a chance to work for top tech giants, check out our course on Post Graduate Program in Full Stack Web Development. In this course, you will learn the complete end-to-end technologies/skills that will help you to set your foot into professional web development. These include Java, DevOps, Agility, HTML, AWS, etc.

Also, check out the complete list of free online courses by Simplilearn.

If you have any questions for us, please mention them in the comments section and we will have our experts answer them for you.

Happy Learning!

Our Software Development Courses Duration And Fees

Software Development Course typically range from a few weeks to several months, with fees varying based on program and institution.

Program NameDurationFees
Caltech Coding Bootcamp

Cohort Starts: 16 Dec, 2024

6 Months$ 8,000
Automation Test Engineer Masters Program

Cohort Starts: 27 Nov, 2024

8 months$ 1,499
Full Stack Java Developer Masters Program

Cohort Starts: 18 Dec, 2024

7 months$ 1,449
Full Stack (MERN Stack) Developer Masters Program

Cohort Starts: 8 Jan, 2025

6 Months$ 1,449