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!