November 22, 2024

Tutorial on Vector Containers in C++ Standard Template Library (STL)

In this tutorial, we provide an introduction to vector containers in C++ Standard Template Library (STL). We wrote a code file that demonstrates how to use and how to perform most of the operations on vector containers. This file is explained in this tutorial and it can also be accessed on this GitHub page.

The YouTube videos accompanying this tutorial are given below. The video tutorial is split into two parts.

In this tutorial you will learn how to:

  • Declare vectors
  • Resize vectors
  • Access entries of vectors by using the classical array approach and by using STL iterators
  • Add and remove entries from vectors
  • Insert entries in vectors
  • Find specific entries in vectors

In C++, vector containers are a part of STL. They are basically dynamic arrays that can automatically change their size when new entries are entered or removed. Elements of vectors can be accessed randomly. The advantage of vectors is that entries at the end of the array can be inserted in a computationally efficient manner. However, that is not the case for entries in the middle or at the beginning of vectors. Another thing to keep in mind about vectors is that their entries are stored in contiguous memory locations. Also, we use iterators (another member of STL that is similar to pointers) to access or modify vectors.

Let us immediately start. First, we need to import the necessary libraries

#include <iostream>
#include <vector>
// to use find
#include<bits/stdc++.h>
using namespace std;

Then, we start with “int main()” function. The code lines explained below should be entered in the main file (do not forget to include the libraries given above).

Vector declarations

We can declare the vectors as follows

	// declarations
	// declaring vectors
	vector<int> vector1;
	// declaring a vector container of integer type of size 5
	vector<int> vector2(5);
	// declare a vector container of integer type of size 6, and initialize the entries to 2
	vector<int> vector3(6,2);

The notation “<int>” in the code line 3, means that the vectors are of type integer. This notation is used in templates. Templates are basically generic structures that can be defined for any data type. For example, we could also define a vector of floats like this:

vector <float> vectorOfFloats;

The code line 5 declares a vector whose size is 5. On the other hand, the code line 7 declares a vector whose size is 6 and at the same time, this code line initialized the vector entries to 2.

Add entries to the vector end

We can add entries to the end of a vector by using these code lines

	// add 15,20,2,-1,-10, -5, 25 to the vector
	vector1.push_back(15);
	vector1.push_back(20);
	vector1.push_back(2);
	vector1.push_back(-1);
	vector1.push_back(-10);
	vector1.push_back(-5);
	vector1.push_back(25);

The C++ function is “push_back()”, and the argument should be an element that should be placed at the end of the vector.

Accessing and printing vector entries individually

We can access and print vector entries individually by using these code lines

	// accesing and printing the entries individually
	cout<<vector1[0]<<endl; //indexing starts from 0 similarly to the indexing of arrays
	cout<<vector1.at(1)<<endl;
	cout<<vector1.front()<<endl;
	cout<<vector1.back()<<endl;		

The first method is to use the standard array notation “[ ]” . The second approach is to use “vector.at()” function. We can also access entries at the beginning or at the end of the vector by using “vector.front()” or “vector.back()” functions.

Printing vector entries by using two approaches

We can print the vector entries by using two approaches. The first approach relies upon the classical array-style access of vector entries. The function used to print the vector entries in this manner is defined below.

// print the entries of the input vector
// by using the first approach - array-style indexing
void printVectorClassical(vector<int> &vectorToBePrinted)
{
	cout<<"Printing the vector entries by using the array-style indexing!"<<endl;
	for (int i=0; i<vectorToBePrinted.size();i++)
	{
		cout<<vectorToBePrinted[i]<<endl; // here we index the vector by using the classical array-style indexing
	}
	// vectorToBePrinted.size() - returns the number of elements in the vector
}

In the code line 6, we can automatically determine the size of a vector by using the function “vector.size()”. The second approach for printing the vectors is more interesting and probably new to you. This approach relies upon iterators. Iterators are basically a generalization of a pointer. They are used to access or change entries of a vector. They are also a part of STL. Roughly speaking, iterators are used to “point” to memory locations of STL containers. We can perform basic arithmetic on iterators, and we can also use the increment, decrement or dereferencing operator (*). The vector as well some other STL template classes, have several member functions that return iterator objects that point to specific elements of the data structure. The most widely used member functions are

  • vector.begin() – returns an iterator that points to the first element (entry) of the vector.
  • vector.end() – returns an iterator that points to the position that is immediately after the last entry of the vector. This member function can be used to test whether an iterator has passed the last entry in the vector. It is very similar to the “nullptr” or “NULL” pointers.

Here is a function that uses iterators in order to print the vector entries:

// print the entries of the input vector
// by using the second approach - approach based on iterators
void printVectorIterators(vector<int> &vectorToBePrinted)
{
	// here we define an iterator
	vector<int>::iterator vectorIterator;
	cout<<"Printing the vector entries by using vector iterators!"<<endl;
	
	for(vectorIterator=vectorToBePrinted.begin(); vectorIterator!=vectorToBePrinted.end();vectorIterator++)
	{
		cout<< *vectorIterator <<endl; // use the dereferencing operator to print the current data of the iterator
	}
	//vectorToBePrinted.begin() returns an iterator located at the first element of the vector
	//vectorToBePrinted.begin() returns an iterator located immediatelly after the last element in the vector
}

We declare an iterator by using this code line

 // here we define an iterator
    vector<int>::iterator vectorIterator;

We first have to specify “vector<int>” in order to tell to the compiler that this is an iterator associated with vector.

Then, this for loop is used to print iterators:

    for(vectorIterator=vectorToBePrinted.begin(); vectorIterator!=vectorToBePrinted.end();vectorIterator++)
    {
        cout<< *vectorIterator <<endl; // use the dereferencing operator to print the current data of the iterator
    }

The for loop runs from the iterator returned by “vectorToBePrinted.begin()”, and it ends when we reached one entry after the last entry of the vector. This entry is “vectorToBePrinted.end()”. We simply increases the value of the iterator by using “vectorIterator++)”. We access the value stored at the entry to which the iterator points by using the dereferencing operator: “*vectorIterator”. That is it! Simple as that! In our main code, we can print the entries of arrays by typing

	// two ways for printing vectors
	printVectorClassical(vector1);
	printVectorIterators(vector1);

Information about vectors and resizing

We can obtain basic information about vector and we can resize vectors by using these code lines

	// information about vectors
	cout<<"vector1 size is: "<<vector1.size()<<endl;
	// resize the vector
	vector2.resize(10); // 0s are placed automatically at new entries
	cout<<"vector1 size is: "<<vector1.size()<<endl;
	printVectorIterators(vector2); 
	// resize with a specific number set to be copied at the empty spots
	int numberToCopy=2;
	vector2.resize(20,numberToCopy);
	printVectorIterators(vector2); 	
	

The size of the vector can be obtained by using “vector.size()”. We can resize the vector by using “vector.resize()”. Note that entries that initially do not exist are set to 0. We can control the entry values that are entered while resizing by directly specifying the entry that should be placed at the non-existing entries. This can be done by using:

int numberToCopy=2;
vector2.resize(20,numberToCopy);

Inserting and deleting entries

We can remove the entry from the back or insert an entry at an arbitrary position by using these code lines:

	// remove the last entry
	cout<<"Removing last two entries"<<endl;
	// remove the last two entries of the vector
	// first remove -10
	vector1.pop_back();
	// then remove -1
	vector1.pop_back();
	printVectorIterators(vector1);
	
	//delete an entry at a specific position
	unsigned int positionToBeErased=1; // positions start from 0
	vector<int>:: iterator vectorIterator=vector1.begin();
	vector1.erase(vectorIterator+positionToBeErased);
	printVectorIterators(vector1);
	
	//delete entries from an interval
	unsigned int interval=3;
	vector1.erase(vectorIterator,vectorIterator+interval);  // not including the entry at "vectorIterator+interval"
	printVectorIterators(vector1);
	
	// insert an entry at a specific location
	vector<int>:: iterator vectorIteratorInsert=vector1.begin();
	int elementToInsert=1000;
	vector1.insert(vectorIteratorInsert+1,elementToInsert); // insert 1000 at the position "vectorIteratorInsert+1"
	printVectorIterators(vector1); 
	// insert copies 
	unsigned int numberOfCopies=5;
	unsigned int elementToInsert2=2000;
	vector1.insert(vectorIteratorInsert+1,numberOfCopies,elementToInsert2);
	printVectorIterators(vector1); 

The function “vector.pop_back()” is used to remove the last entry. The function “vector.erase()” is used to erase an element at a specific location, specified by the input argument iterator. As explained in the code, we can also delete entries belonging to an interval by providing the second argument that specifies the interval. Using the same principle, we can insert the element at a specific location. For that purpose, we use the function “vector.insert()”. By providing an extra argument, we can also insert several copies of the input argument, as it is explained in the code.

Find a specific entry in a vector STL container

There are at least two approaches for finding an entry in the vector container. The first approach relies upon the function “std::find()”. This approach is given below.

	// find a specific entry
	// first approach
	
	int entryToFind=2000;
	
	vector<int>:: iterator findIterator;
	// this function returns an iterator to the first element that is equal to entryToFind
	// if there is no such element in the vector, the function returns iterator to vector1.end()
	findIterator=find(vector1.begin(),vector1.end(),entryToFind);
	if (findIterator!=vector1.end())
	{
	 	cout<<"First entry that matches the search query found at the position "<<findIterator-vector1.begin()<<endl;
	}
	else
	{
		cout<<"The entry is not found!";
	}
	

The function “find()” takes as inputs iterators to the interval that it should focus on, and the last argument is an entry that needs to be find. If the function is able to find the entry, it returns an iterator to the queried entry. Otherwise, it return the iterator that is returned by “vector1.end()”. On the basic of this fact, we can form a simple if statement that will determine if the entry is found or not, as it is explained in the code.

The second approach is very similar to the print function that is based on the iterators (the print function is explained previously). The code is self-explanatory once iterators are properly understood.

	// find a specific entry
	// second approach
	
	int entryToFind2=2000;
	vector<int>:: iterator findIterator2;
	
	for (findIterator2=vector1.begin();findIterator2!=vector1.end();findIterator2++)
	{
		if (*findIterator2==entryToFind2)
		{
			break;
		}
	}
	
	if (findIterator!=vector1.end())
	{
	 	cout<<"First entry that matches the search query found at the position "<<findIterator-vector1.begin()<<endl;
	}
	else
	{
		cout<<"The entry is not found!";
	}

	//erase all the vector entries
	vector1.clear();
	printVectorIterators(vector1);

This is all you need to know to start with iterators and vectors! I hope that you enjoyed this brief tutorial!