About usWhy usInstructorsReviewsCostFAQContactBlogRegister for Webinar

Vector in C++ STL

The Standard Template Library is a set of C++ template classes and contains incredibly useful container classes, algorithms, methods, and iterators. One such container in C++ STL is a vector. This article will help you learn more about it so you can explore how to harness its power as a tool. We’ll discuss:

  • The Container Vector in C++ STL
  • Member Functions of Vector
  • Non-Member Function Overloads
  • Time Complexity Of Common Operations Using Vectors
  • Example — Code and Output
  • FAQs 

The Container Vector in C++ STL

Arrays work well for handling sequences but have this one major limitation: they have a fixed size once declared. The container Vector offers a solution to this problem. 

A vector is a sequence container that represents a dynamic array. So it holds sequences in contiguous memory locations just like an array. But its size can also change dynamically, as the container handles the storage automatically. 

We can use a vector using the following syntax:

#include<vector>

std::vector<dataType> vectorVariableName;


With vectors, we get the benefits of an array, like accessing elements easily at any position using indices, while not being limited by the static size limitation. The same thing (storage in contiguous locations) that allows arrays and vectors quick access to any element in the array also slows down insertion and deletion operations from the middle. 

Shifting the rest of the elements is necessary after removing or inserting an element from the middle, which causes the slowdown.

Hence, vectors share this limitation of having slow insertion and deletion operations from the middle with arrays. Like for other containers in STL, we can iterate over elements in a Vector using an iterator. We can do several other complex operations easily since they are available as member functions for vectors. Let us take a closer look at them.

Member Functions of Vector

Member functions provided for a vector in CPP help us harness the power of a vector as a container. We can utilize these member functions easily and efficiently. Vectors have some basic public member functions: 

  • The constructor function, which constructs a vector
  • The destructor function, which destructs a vector
  • The operator= function, which helps perform assignment operations on vectors

Other than that, there are five types of public member functions associated with vectors in C++:

Iterators

  • begin: We can use it as vectorVariableName.begin() and returns an iterator pointing to the first element.
  • end: We can use it as vectorVariableName.end(), and it returns an iterator to the past-the-end element.
  • rbegin: We can use it as vectorVariableName.rbegin(), and it returns a reverse iterator pointing to the reverse beginning, that is, the last element.
  • rend: We can use it as vectorVariableName.rend(), and it returns a reverse iterator pointing to the theoretical element after the reverse end, that is, the theoretical element before the first element.
  • cbegin: We can use it as vectorVariableName.cbegin(), and it returns a const_iterator pointing to the first element.
  • crbegin: We can use it as vectorVariableName.crbegin(), and it returns a const_reverse_iterator to the reverse beginning.
  • cend: We can use it as vectorVariableName.cend(), and it returns a const_iterator to the past-the-end element.
  • crend: We can use it as vectorVariableName.crend(), and it returns a const_reverse_iterator to the reverse past-the-end element (element preceding the first element in the vector).

Capacity

  • size: We can use it as vectorVariableName.size(), and it returns the size of the vector.
  • max_size: We can use it as vectorVariableName.max_size(), and it returns the maximum number of elements the vector can store.
  • resize: We can use it as vectorVariableName.resize(newSize,defaultValue), and it changes the size of the vector, storing the default value in the new elements that don’t have any value yet. We can also use it as vectorVariableName.resize(newSize). The default values here will work as usual (For example, vector of type int will have default value 0 unless stated otherwise).
  • capacity: We can use it as vectorVariableName.capacity(), and it returns the size of allocated memory for the vector in terms of the number of elements.
  • empty: We can use it as vectorVariableName.empty(), and it returns a boolean stating whether the vector is empty or not.
  • reserve: We can use it as vectorVariableName.reserve(newSize), and it requests a change in the overall memory allocated to the vector.
  • shrink_to_fit: We can use it as vectorVariableName.shrink_to_fit(), and it shrinks the vector capacity to fit just the elements stored in it and get rid of extra allocated space.

Element Access

  • operator[]: We can use it as  vectorVariableName[index] to access an element in the vector.
  • at: We can use it as vectorVariableName.at(index) to access an element in the vector.
  • front: We can use it as vectorVariableName.front() to access the first element in the vector.
  • back: We can use it as vectorVariableName.back() to access the last element in the vector.
  • data: We can use it as vectorVariableName.data(), and it returns a pointer to the memory array (the first element in the array) used internally by a vector. 

Modifiers

  • assign: We can use it as  vectorVariableName.assign(numberOfItems,defaultValue) to assign a number of values with a given default value to the vector. It can also be used as vectorVariableName.assign(firstIterator,lastIterator) to take all elements present in a container from one position to the other and assign them to the vector.
  • push_back: We can use it as vectorVariableName.push_back(value) to add an element at the end of the vector.
  • pop_back: We can use it as vectorVariableName.pop_back() to remove/delete the last element from the vector.
  • insert: We can use it as  vectorVariableName.insert(position, value) to insert a value at a particular position, or as vectorVariableName.insert(position, numberOfElements, value) to add some number of elements having a particular value at a particular position. We can also use it as vectorVariableName.insert(position, firstIterator, lastIterator) to insert elements present in a container from some position to the other into the vector at a particular position.
  • erase: We can use it as vectorVariableName.erase(position) to erase an element at that position. We can also use it as vectorVariableName.erase(firstIterator, lastIterator) to erase all elements in a given range of positions.
  • swap: We can use it as vectorVariableName.swap(anotherVector) to swap contents stored in two vectors.
  • clear: We can use vectorVariableName.clear() to remove all elements and destroy them, leaving the vector’s size zero.
  • emplace: We can use it as vectorVariableName.emplace(position, value) to construct and insert an element into the vector at a given position.
  • emplace_back: We can use it as ectorVariableName.emplace_back(value) to construct and insert an element at the end of the vector.

Allocator

  • get_allocator: We can use it as vectorVariableName.get_allocator() to get allocator, which can then be used to allocate and deallocate memory, construct and destruct values at certain positions, etc. 

Non-Member Function Overloads

  • relational operators: It performs comparison operations between vectors, like if they are equal, unequal, greater/less than, greater/less than or equal to, etc. It returns a boolean representing the truth-value of the comparison. Their usage looks like v1!=v2, v1<=v2, and so on.
  • swap: It is used exactly as the generic swap, i.e.,  vector1.swap(vector2), except that it has improved performance. It can achieve this as the vectors exchange reference to their data instead of copying elements or moving them. 

Time Complexity Of Common Operations Using Vectors

Example

Now we’ll see how we can use these member functions through an example:

Code

#include <iostream>

#include <vector>

using namespace std;

int main()

{

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

    cout << "Element access member functions\n";


    cout<< "\nvalue at index 2: "<< vectorVariableName[2];

    cout<< "\nvalue at index 2: "<< vectorVariableName.at(2);

    cout<< "\nfirst element: "<< vectorVariableName.front();

    cout<< "\nlast element: "<< vectorVariableName.back();

    cout<< "\naddress of vector or address of first element: "<< vectorVariableName.data();

    

    cout << "\n"<< "\nCapacity member functions\n";


    cout<<"\nvector size: "<< vectorVariableName.size();

    cout<<"\nvector max size: "<< vectorVariableName.max_size();

    cout<<"\nvector capacity: "<< vectorVariableName.capacity();

    cout<<"\nIs vector empty: "<< vectorVariableName.empty();

    

    vectorVariableName.resize(10,100);

    cout<<"\nvector size after resizing: "<< vectorVariableName.size();

    

    vectorVariableName.reserve(50);

    cout<<"\nvector capacity after reserving more memory: "<< vectorVariableName.capacity();

    

    vectorVariableName.shrink_to_fit();

    cout<<"\nvector capacity after shrinking to fit: "<< vectorVariableName.capacity();

    

    cout << "\n"<<"\nIterator member functions\n";


    cout << "\nUsing begin and end: ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " ";

    

    cout << "\nUsing cbegin and cend: ";

    for (auto i = vectorVariableName.cbegin(); i != vectorVariableName.cend(); ++i)

        cout << *i << " ";

    

    cout << "\nUsing rbegin and rend: ";

    for (auto j = vectorVariableName.rbegin(); j != vectorVariableName.rend(); ++j)

        cout << *j << " ";

    

    cout << "\nUsing crbegin and crend: ";

    for (auto j = vectorVariableName.crbegin(); j != vectorVariableName.crend(); ++j)

        cout << *j << " ";

        

    cout << "\n"<< "\nModifier member functions\n\n";

   

    cout <<"Vector before push_back(22): ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " ";

    cout <<"\n";


    //adding 22 to the vector

    vectorVariableName.push_back(22);

        

    cout <<"Vector after push_back(22): ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " "; 

    cout <<"\n";


    //assign 5 values, all equal to 1

    vectorVariableName.assign(5,1);

       

    cout <<"Vector after assign(5,1): ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " ";

    cout <<"\n";


    //inserting value 1000 at index 0

    vectorVariableName.insert(vectorVariableName.begin(), 1000);

    

    cout <<"Vector after insert 1000 at beginning: ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " ";

    cout <<"\n";


    //removing one value from the end

    vectorVariableName.pop_back();

    

    //erasing value at index 2

    vectorVariableName.erase(vectorVariableName.begin()+2);

         

    cout <<"Vector after pop_back and erase begin()+2: ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " "; 

    cout <<"\n";

    

    //creating and inserting value 101 at the end of the vector

    vectorVariableName.emplace_back(101);

    

    //creating and inserting value 0 at index 5

    vectorVariableName.emplace(vectorVariableName.begin()+5, 3);

    

    //Checking the vector now

    cout << "\nVector after emplace operations: ";

    for (auto i = vectorVariableName.begin(); i != vectorVariableName.end(); ++i)

        cout << *i << " ";

    

    //creating new vector, swapping values with original

    vector<int> anotherVector;

    vectorVariableName.swap(anotherVector);

    cout << "\nNew vector after swapping contains: ";

    for (auto i = anotherVector.begin(); i != anotherVector.end(); ++i)

        cout << *i << " ";

    

    //removing all elements from new vector

    anotherVector.clear();

    cout << "\nThe size of the new vector after using clear: "<< anotherVector.size();

    

    cout << "\n"<< "\nAllocator member function\n"; 


    anotherVector.get_allocator().allocate(10);

    cout << "\nThe capacity of the vector after using allocate(10): "<<anotherVector.capacity();

    return 0;

}

Output

Element access member functions

value at index 2: 3

value at index 2: 3

first element: 1

last element: 5

address of vector or address of first element: 0x9eb7a10


Capacity member functions

vector size: 5

vector max size: 1073741823

vector capacity: 5

Is vector empty: 0

vector size after resizing: 10

vector capacity after reserving more memory: 50

vector capacity after shrinking to fit: 10


Iterator member functions

Using begin and end: 1 2 3 4 5 100 100 100 100 100 

Using cbegin and cend: 1 2 3 4 5 100 100 100 100 100 

Using rbegin and rend: 100 100 100 100 100 5 4 3 2 1 

Using crbegin and crend: 100 100 100 100 100 5 4 3 2 1 


Modifier member functions

Vector before push_back(22): 1 2 3 4 5 100 100 100 100 100 

Vector after push_back(22): 1 2 3 4 5 100 100 100 100 100 22 

Vector after assign(5,1): 1 1 1 1 1 

Vector after insert 1000 at beginning: 1000 1 1 1 1 1 

Vector after pop_back and erase begin()+2: 1000 1 1 1 


Vector after emplace operations: 1000 1 1 1 101 3 

New vector after swapping contains: 1000 1 1 1 101 3 

The size of the new vector after using clear: 0


Allocator member function

The capacity of the vector after using allocate(10): 20

FAQs 

Question 1: What are some differences between arrays and vectors?

Question 2: How is storage handled dynamically in a vector?

Vectors internally use a dynamically allocated array for storage. Since allocating a larger array for each insertion is expensive, vectors don’t heavily rely on that. That said, they do use this when necessary. Instead, vectors usually allocate some extra space to accommodate the possibility of insertion of more elements. 

Hence the vector’s actual capacity is often more than what’s required, making it less memory efficient than arrays. When we need to insert a new element and the vector is full, the vector increases its size to twice the current size.

Question 3: What are some differences between lists and vectors?

Recommended Reading

Are you a software engineer looking for coding interview questions to aid your technical interview prep? Check out these useful pages for software developers:

Are You Ready to Nail Your Next Coding Interview?

Whether you’re a Coding Engineer gunning for Software Developer or Software Engineer roles, or you’re targeting management positions at top companies, IK offers courses specifically designed for your needs to help you with your technical interview preparation!

If you’re looking for guidance and help with getting started, sign up for our free webinar. As pioneers in the field of technical interview prep, we have trained thousands of Software Engineers to crack the most challenging coding interviews and land jobs at their dream companies, such as Google, Facebook, Apple, Netflix, Amazon, and more!

Sign up now!

————

Article contributed by Tanya Shrivastava


Attend our Free Webinar on How to Nail Your Next Technical Interview

Recommended Posts

All Posts