How Does a Vector Internally Works in C++?
Last Updated :
15 Nov, 2024
In C++, a vector is a dynamic array that can resize itself when more elements are added or deleted. So, one may ask that how a vector internally works to achieve its dynamic resizing capability while maintaining similar efficiency to static arrays in operations?
For vector to work as a resizable dynamic array, it has to implement the following features:
- Random Access using Index: Quick access to elements using index, with O(1) time complexity.
- Dynamic Resizing: The size should automatically change according to elements inserted or deleted without any user interference.
- Fast Insertion and Deletion at the End: Insertion and deletion of the elements at the end of the vector must provide O(1) time complexity.
- Homogeneous Elements: All the elements must be of same type.
Implementation of Features
Let's discuss how the above features can be implemented in the vector:
- Random Access Using Index: To provide random access to the elements using index, all the elements of the vector should be stored continuously in the memory. It is possible by allocating a block of memory in the heap using new operator.
- Dynamic Resizing: For dynamic resizing, the whole block of vector memory has to be reallocated to the larger size using new operator when the vector becomes full.
- Homogeneous Elements: The block returned by the new operator already allocate the memory of given number of elements of same type.
- Fast Insertion and Deletion at the End: If the vector already has enough space, there is no issues with providing O(1) insertion at the end. But if the vector is full, a reallocation is needed.
Internal Working of Vector
Let's understand the internal working by taking the basic use of the vector step-by-step as a reference:
Creating a Vector
When an empty vector is created, a memory block of a default size is allocated in the head. The size of this memory block is called capacity of the vector.
Inserting Elements
When an element is inserted, it is copied to the allocated memory and the number of stored elements. We can keep inserting element like this till the size is equal to the capacity, which means that the vector is full. To insert more elements, a reallocation needed to be done.
Reallocation
In reallocation, we encounter an issue. You see, reallocating a memory block doesn't extent it in place, instead, it copies the whole block to the new block of larger size, which will take O(n). So, if a reallocation is done at each insertion or deletion, it will increase the time complexity by a factor of O(n).
To provide the fast insertion and deletion at the end while maintaining the vector's dynamic resizing capability, the exponential growth policy is used for reallocation. According to this policy,
Initially, a memory block of fixed size allocated for vector. Whenever the vector becomes full and needs resizing, instead of increasing the size of the memory block by just one element, it is doubled in size.
One may argue here that the complexity of reallocation is still not changed and remains O(n), but the number of times reallocation is needed is reduced exponentially leading to amortized complexity of inserting element at the end to be O(1). Refer to the article Amortized Analysis Introduction for mathematical proof.
Deleting Elements
Deleting elements does not trigger any reallocation. The object deleted will be destroyed but the memory would still belong to the vector.
Example: Suppose a vector starts with an initial size of 1:
- Insert 1st element: Size = 1, Capacity = 1 (no reallocation needed).
- Insert 2nd element: Size = 2, Capacity = 2 (reallocation needed, copy 1 element).
- Insert 3rd element: Size = 3, Capacity = 4 (reallocation needed, copy 2 elements).
- Insert 4th element: Size = 4, Capacity = 4 (no reallocation needed).
- Insert 5th element: Size = 5, Capacity = 8 (reallocation needed, copy 4 elements).
We can actually verify this copying in a C++ program using a vector of a custom data type that signals whenever its object is copied.
C++
#include <bits/stdc++.h>
using namespace std;
// Custom data type to track copying
class C {
public:
int a;
C(int x = 0): a(x){}
// Copy Constructor
C(const C& other) : a(other.a) {
cout << "Copying C(" << a << ")\n";
}
};
// Main function to demonstrate the behavior
int main() {
vector<C> v;
// Pushing 8 elements
for (int i = 0; i < 8; i++) {
v.emplace_back(i + 1);
}
return 0;
}
OutputCopying C(1)
Copying C(1)
Copying C(2)
Copying C(1)
Copying C(2)
Copying C(3)
Copying C(4)
As we can see, the elements are copied exactly 8 times which was predicted above. This proves that the vector internally uses the exponential growth.
Note:vector emplace_back() is used to avoid the extra copies of elements.
Summary
From this article, we can summarize the working of the vector as:
- Initially, a vector is allocated default amount of memory.
- When the vector becomes full, reallocation is done.
- Reallocation follows exponential growth by doubling the size of the memory block ensuring fewer reallocations for efficiency.
- While insertion and deletion at the end are not strictly O(1), they achieve an amortized time complexity of O(1).
- Deleting elements destroys the object but does not trigger memory reallocation.
Similar Reads
Vector in C++ STL C++ vector is a dynamic array that stores collection of elements same type in contiguous memory. It has the ability to resize itself automatically when an element is inserted or deleted.Create a VectorBefore creating a vector, we must know that a vector is defined as the std::vector class template i
7 min read
8 Ways to Initialize Vector in C++ Initializing a vector means assigning some initial values to the std::vector elements. In this article, we will learn 8 different ways to initialize a vector in C++.Table of ContentUsing Initializer ListOne by One InitializationWith a Single ValueFrom an ArrayFrom Another VectorFrom Any STL Containe
5 min read
Commonly Used Methods
Vector end() in C++ STLIn C++, the vector end() is a built-in method used to obtain an iterator pointing to the theoretical element after the last element of the vector. Even though this iterator does not point to a valid element, it serves as a marker for the end of the vector.Letâs take a look at an example that illustr
3 min read
Vector empty() in C++ STLIn C++, vector empty() is a built-in method used to check whether the given vector is empty or not. In this article, we will learn about vector empty() method in C++.Letâs take a look at an example that illustrates the vector empty() method:C++#include <bits/stdc++.h> using namespace std; int
2 min read
Vector operator[ ] in C++ STLIn C++, the vector operator [] is used to randomly access or update the elements of vector using their indexes. It is similar to the vector at() function but it doesn't check whether the given index lies in the vector or not.Letâs take a look at a simple code example:C++#include <bits/stdc++.h
3 min read
Vector front() in C++ STLIn C++, the vector front() is a built-in function used to retrieve the first element of the vector. It provides a reference to the first element, allowing you to read or modify it directly.Letâs take a quick look at a simple example that uses the vector front() method:C++#include <bits/stdc++.h
2 min read
Vector push_back() in C++ STLIn C++, the vector push_back() is a built-in method used to add a new element at the end of the vector. It automatically resizes the vector if there is not enough space to accommodate the new element.Letâs take a look at an example that illustrates the vector push_back() method:C++#include <bits/
2 min read
Vector insert() in C++ STLIn C++, the vector insert() is a built-in function used to insert new elements at the given position in a vector. In this article, we will learn about the vector insert() function in C++. Letâs take a look at an example that shows the how to use this function:C++#include <bits/stdc++.h> using
4 min read
vector emplace() in C++ STLIn C++, vector emplace() is used to insert elements at the given position in a vector by constructing it in-place within the vector, rather than creating a temporary object and then moving or copying it into the vector.Let's take a quick look at a simple example that uses vector emplace() method:C++
3 min read
Vector assign() in C++ STLIn C++, the vector assign() is a built-in method used to assign the new values to the given vector by replacing old ones. It also modifies the size of the vector according to the given number of elements. Letâs take a look at an example that shows the how to use this function.C++#include <bits/st
4 min read
Vector erase() in C++ STLIn C++, vector erase() is a built-in function that is used to delete elements from the vector. It removes an element of a specific position or range of elements from the vector. Letâs take a simple example that uses the vector erase() method:C++#include <bits/stdc++.h> using namespace std; int
3 min read
Other Member Methods
Vector max_size() in C++ STLIn C++, vector max_size() is a built-in function used to find the maximum number of elements that can be held by the vector container. In this article, we will learn about the vector max_size() function in C++.Let's take a look at an example that illustrates this method:CPP#include <bits/stdc++.h
3 min read
Vector capacity() in C++ STLIn C++, the vector capacity() is a built-in method used to find the capacity of vector. The capacity indicates how many elements the vector can hold before it needs to reallocate additional memory. In this article, we will learn about vector capacity() method in C++.Letâs take a look at an example t
3 min read
vector rbegin() and rend() Functions in C++ STLIn C++, std::vector::rbegin() and std::vector::rend() are built-in functions used to retrieve reverse iterators to the reverse beginning and reverse end of a vector. These functions allow easy traversal of vectors in reverse i.e. from the last element to the first. They are the member functions of t
3 min read
vector :: cbegin() and vector :: cend() in C++ STLVectors are known as dynamic arrays which can change its size automatically when an element is inserted or deleted. This storage is maintained by container. vector::cbegin() The function returns an iterator which is used to iterate container. The iterator points to the beginning of the vector.Iterat
2 min read
Vector crend() in C++ STLIn C++, the vector crend() is a built-in method used to obtain a constant reverse iterator pointing to the theoretical element just before the first element of the vector. It is used to mark the reverse end of the vector.Letâs take a look at an example: C++#include <bits/stdc++.h> using namesp
2 min read
Vector resize() in C++ STLIn C++, the vector resize() is a built-in method used to change the size of vector container after it is declared. It can be used to increase or decrease the size of vector.Letâs take a look at an example that illustrates the vector resize() method:C++#include <bits/stdc++.h> using namespace s
3 min read
Vector shrink_to_fit() in C++ STLIn C++, vector shrink_to_fit() is a built-in function used to reduce the capacity of the vector to fit its size and destroys all elements beyond the size. In this article we will learn about vector shrink_to_fit() in C++.Letâs take a quick look at an example that illustrates vector shrink_to_fit() m
2 min read
When to use Vector reserve() in C++?In a vector, when the number of elements to be inserted are greater than the current capacity, it is reallocated to a larger memory block and all the items are copied to this new block making this reallocation an expensive operation with time complexity of O(n).This mechanism works well if you don't
2 min read
Vector data() in C++ STLIn C++, the vector data() is a built-in function used to access the internal array used by the vector to store its elements. In this article, we will learn about vector data() in C++.Letâs take a look at an example that illustrates the vector data() method:C++#include <bits/stdc++.h> using nam
2 min read
2D Vector in C++ A 2D vector is a vector of the vectors i.e. each element is a vector in itself. It can be visualised as a matrix where each inner vector represents a row, and the number of rows represents the maximum columns. A 2D vector is dynamically resizable in both dimensions.SyntaxC++vector<vector<data_
7 min read
Passing Vector to a Function in C++ To perform operations on vector belonging to one function inside other function, we pass this vector to the function as arguments during the function call.C++ provides three methods to pass a vector to a function in C++. Let's look at each of them one by one.Table of ContentPass Vector by ValuePass
5 min read
How Does a Vector Internally Works in C++? In C++, a vector is a dynamic array that can resize itself when more elements are added or deleted. So, one may ask that how a vector internally works to achieve its dynamic resizing capability while maintaining similar efficiency to static arrays in operations?For vector to work as a resizable dyna
5 min read
How to implement our own Vector Class in C++? The given task is to implement a class in C++ which behaves just like the Vector class.Vectors are the same as dynamic arrays with the ability to resize themselves automatically when an element is inserted or deleted, with their storage being handled automatically by the container. Vector elements a
5 min read
Advantages of Vector Over Array in C++ In C++, both vectors and arrays are used to store collections of elements, but vector offers significant advantages over arrays in terms of flexibility, functionality, and ease of use. This article explores the benefits of using vectors in C++ programming.The major advantages of vector over arrays a
3 min read
Common Vector Programs