We will be discussing the following things in this Vectors in C++ blog:
Table of Contents
What is Vector in C++?
A vector is a resizable array that can grow or shrink as you add or remove any element. It’s a part of a C++ library called the Standard Template Library (STL) that makes working with collections of similar types of data easier and more flexible.
It has functionalities like dynamic resizing, insertion, deletion, accessing elements via index, and more. Vector is a more flexible alternative to array because they can automatically manage memory allocation.
When to Use Vectors in C++
Here are some scenarios where you should use a vector rather than an array:
- Unknown Size of Data at Runtime: Vectors are useful when you don’t know the exact number of elements that you want to store initially because they can dynamically grow or shrink as needed.
- Frequent Insertions and Deletion of Data: Vector is efficient for adding and removing elements at any position because of its auto-resizing ability, especially when you need to insert or remove data frequently. Traditionally, in array, you do need to redefine its size.
- Helpful in Making Copies: When you need to make copies of your data, Vector in C++ supports multiple inbuilt-functions for copying data.
Declaration of Vector in C++
Let’s understand step by step how we can declare a Vector in C++:
Step 1: For using vector in your program, first you need to include the ‘vector’ header file with the help of the following command:
#include <vector>
Step 2: After including the header file, you can declare the vector using template syntax as follows:
vector<data_type> vector_name;
Let’s understand the structure of above syntax:
- ` vector`: This is the name of the vector class in the C++ Standard Template Library (STL).
- `<data_type>`: This specifies the type of elements that the vector will store (e.g., <int>, <double>, <string>, or custom types).
- `vector_name`: This is the name you choose for your vector as you want for example, you can name yout vector as Vector1 , newvector, etc.
Examples:
Here is an example of declaring vectors for different data types:
// Vector of integers
vector<int> numbers;
// Vector of strings
vector<string> names;
// Vector of custom objects
struct Person {
string name;
int age;
};
vector<Person> people;
Initialization of a Vector in C++
After declaring a vector, we need to initialize it to store elements of a particular data type. There are many methods to initialize Vector in C++, let’s understand them with the help of examples:
1. Initializing like Arrays:
Initializes a vector with a specific set of values that will be defined in curly brackets separated by commas.
vector<int> numbers = {1, 2, 3, 4, 5};
vector<string> names = {"Alice", "Bob", "Charlie"};
// Initializing the vector with Person objects, Here, person is user-defined struct data type, as we have declared earlier
vector<Person> people = { {"Alice", 25}, {"Bob", 30}, {"Charlie", 22} };
2. Initializing all Elements with a Particular Value:
Creates a vector of a specified size, filled with the same value. As you can see in the below line of code, we have created a vector that will contain 10 zeros.
vector<int> tenZeroes(10, 0); // Vector of size 10, all initialized to value ‘0’
//elements in Vector ‘tenZeroes’ : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
3. Initializing from another Vector:
Initializes a vector with the help of another vector. As you can see in the below lines of code, we have used begin() and end() functions to denote from where ‘vec2’ vector will start accessing the elements and till where. Here, ‘vec2’ will have following elements : {10, 20, 30}
vector<int> vect1{ 10, 20, 30 };
vector<int> vect2(vect1.begin(), vect1.end());
//elements in vector ‘vec2’ : { 10, 20, 30 }
4. Initializing from an Array:
Initializes a vector with elements from another range of elements. For example, in the below-mentioned line of code, we have used an array ‘arr[ ]’ to copy the values in a Vector.
int arr[ ] = { 100, 200, 300 , 400 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vect(arr, arr + n);
//elements in vector ‘vect’ : { 100, 200, 300 , 400 }
5. Initializing by Pushing Values one by one:
Adds elements to the end of an existing vector one by one. This is done with the help of push_back() function.
vector<int> numbers;
numbers.push_back(42);
numbers.push_back(17);
//elements in vector ‘number’ : { 42, 17 }
6.Assigning Values:
Assigns values to specific indexes after declaration. The following line code will assign the values at 0 and 2 index of a vector with a size defined as 5.
vector<int> numbers(5); // Vector of 5 elements with default values
numbers[0] = 10;
numbers[2] = 25;
//elements in vector ‘numbers’ : { 10, 0, 25, 0, 0 }
Basic Vector Operations
Let’s understand the different operations that we can perform with Vectors in C++:
Inserting Elements at the End in a Vector
In C++, `push_back()` function is used to insert elements at the end of a vector. It dynamically increases the vector’s size and adds elements to the back. Here is an example that explains how push_back() is used for element insertion:
vector<int> myVector;
// Insert elements at the end by using push_back()
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
After execution, `myVector` will contain `{10, 20, 30}` as elements, inserted in sequential order.
Accessing Elements of a Vector
Elements in a vector can be accessed using indexing (`[ ]`). It allows the retrieval of elements based on the index position of the element. Here is an example that shows how we can randomly access the element of the vector:
vector<int> myVector = {10, 20, 30, 40, 50};
// Access elements using index []
cout << "Element at index 2: " << myVector[2] << endl;
In this example, accessing `myVector[2]` retrieves the element at index 2, which is `30`.
Another way of accessing the first and last elements of the vector can be done with the help of iterators. Iterators in C++ (`begin()` and `end()`) allow traversing through a container, such as a vector, and accessing its elements.
vector<int> myVector = {10, 20, 30, 40, 50};
// Access elements using iterators
for (auto it = myVector.begin(); it != myVector.end(); ++it) {
cout << *it << " ";
}
The ‘for’ loop in the above example traverses through `myVector` using iterators and prints each element.
Changing Vector Elements
Elements in a vector can be modified using indexing (`[ ]`). It allows for changing elements based on their index positions. Let’s understand this with the help of the following example:
vector<int> myVector = {10, 20, 30, 40, 50};
// Change element at index 3
myVector[3] = 100;
After execution, `myVector` will be modified to `{10, 20, 30, 100, 50}`.
Deleting Elements from Vectors
Let’s understand the usage of functions with which we can delete elements in a vector:
`pop_back()` Function
If we want to remove the last element from a vector then we can use the pop_back() function. After execution, vector `myVector` will become `{10, 20, 30, 40}`, as the last element (`50`) is removed.
vector<int> myVector = {10, 20, 30, 40, 50};
// Delete the last element
myVector.pop_back();
`erase()` Function
To delete the element at the specified position or a range of positions in a vector, we use erase() function. After execution, `myVector` will be `{10, 20, 40, 50}` as the element at index 2 which is `30` will be removed.
vector<int> myVector = {10, 20, 30, 40, 50};
// Delete element at index 2
myVector.erase(myVector.begin() + 2);
Vector Functions in C++
The Standard Template Library(STL) of C++ supports various functions and operations for vector for the efficient manipulation of elements.
Here are some key functions and operations of Vectors in C++:
Vector Iterators
Vector Iterators are used to traverse Vector. These iterators point to a particular element in the Vector and from that element by incrementing the iterator position we can traverse the Vector. Here is a list of some commonly used iterator functions of Vector in C++:
Function | Description | Sample Code |
begin() | Returns an iterator to the first element | vector<int> myVec = {1, 2, 3}; vector<int>::iterator it = myVec.begin(); |
end() | Returns an iterator one past the last element | vector<int> myVec = {1, 2, 3}; vector<int>::iterator it = myVec.end(); |
rbegin() | Returns a reverse iterator one before the first element | vector<int> myVec = {1, 2, 3}; vector<int>::reverse_iterator rit = myVec.rbegin(); |
rend() | Returns a reverse iterator to the last element | vector<int> myVec = {1, 2, 3}; vector<int>::reverse_iterator rit = myVec.rend(); |
cbegin() | Returns a constant iterator to the first element | vector<int> myVec = {1, 2, 3}; vector<int>::const_iterator cit = myVec.cbegin(); |
cend() | Returns a constant iterator one past the last element | vector<int> myVec = {1, 2, 3}; vector<int>::const_iterator cit = myVec.cend(); |
crbegin() | Returns a constant reverse iterator to the last element | vector<int> myVec = {1, 2, 3}; vector<int>::const_reverse_iterator crit = myVec.crbegin(); |
crend() | Returns a constant reverse iterator one before the first element | vector<int> myVec = {1, 2, 3}; vector<int>::const_reverse_iterator crit = myVec.crend(); |
Here is a program that shows the implementation of all the above-mentioned functions:
#include <iostream>
#include <vector>
int main() {
vector<int> numbers = {1, 2, 3, 4, 5};
// Using begin() and end()
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// Using rbegin() and rend() to iterate in reverse
for (auto it = numbers.rbegin(); it != numbers.rend(); ++it) {
cout << *it << " ";
}
cout << endl;
// Using cbegin() and cend() with const_iterator
for (auto it = numbers.cbegin(); it != numbers.cend(); ++it) {
cout << *it << " ";
}
cout << endl;
// Using crbegin() and crend() with const_reverse_iterator
for (auto it = numbers.crbegin(); it != numbers.crend(); ++it) {
cout << *it << " ";
}
cout << endl;
return 0;
}
Vector Capacity Functions
Capacity functions are used to define the size and capacity of a vector. Here is a list of some commonly used capacity functions of Vector in C++:
Function | Description | Sample Code |
size() | Returns the number of elements currently stored in the Vector. | vector<int> myVec = {1, 2, 3}; int numElements = myVec.size(); // numElements will be 3 |
max_size() | Returns the maximum possible size that the Vector can hold, based on system and memory constraints. | vector<int> myVec; int maxPossible = myVec.max_size(); |
resize(n) | Resizes the Vector to hold n elements. If n is larger than the current size, new elements are added with default values. If n is smaller, elements are removed from the end. | vector<int> myVec = {1, 2, 3}; myVec.resize(5); // myVec now holds {1, 2, 3, 0, 0} |
capacity() | Returns the current storage capacity of the Vector, which is the amount of memory that has been allocated for it. This is often larger than the actual number of elements in the Vector. | vector<int> myVec = {1, 2, 3}; int capacity = myVec.capacity(); // capacity might be 4 or more |
empty() | Returns a boolean indicating whether the Vector is empty (i.e., has no elements). | vector<int> myVec; bool isEmpty = myVec.empty(); // isEmpty will be true |
reserve(n) | Requests that the Vector capacity be increased to at least n, to avoid unnecessary reallocations when elements are added. | vector<int> myVec; myVec.reserve(100); // Allocates space for at least 100 elements |
shrink_to_fit() | Requests that the Vector reduce its capacity to match its size, to free up unused memory. | vector<int> myVec = {1, 2, 3}; myVec.shrink_to_fit(); // Capacity is reduced to 3 |
Here is a program that shows the implementation of all the above-mentioned functions:
#include <iostream>
#include <vector>
int main() {
// Creating an empty vector of integers
vector<int> numbers;
// Using size() to get the number of elements
cout << "Size of the vector: " << numbers.size() << endl;
// Using max_size() to get the maximum size the vector can reach
cout << "Maximum size of the vector: " << numbers.max_size() << endl;
// Using empty() to check if the vector is empty
cout << "Is the vector empty? " << (numbers.empty() ? "Yes" : "No") << endl;
// Adding elements to the vector
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
cout << "Elements in the vector: ";
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
// Using resize(n) to change the size of the vector
numbers.resize(5);
// Using capacity() to get the current capacity of the vector
cout << "Capacity of the vector: " << numbers.capacity() << endl;
// Using reserve(n) to reserve memory for a certain number of elements
numbers.reserve(10);
// Using shrink_to_fit() to reduce the capacity to fit the number of elements
numbers.shrink_to_fit();
cout << "After resizing, elements in the vector: ";
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
return 0;
}
Vector Modifiers
Modifire functions are used to modify the data that vector contains. Here is a list of some commonly used modifier functions of Vector in C++:
Function | Description | Sample Code |
assign() | Replaces the contents of the Vector with new elements. | vector<int> myVec = {1, 2, 3}; myVec.assign({4, 5, 6}); // myVec now holds {4, 5, 6} |
push_back() | Adds an element to the end of the Vector. | vector<int> myVec; myVec.push_back(10); // myVec now holds {10} |
pop_back() | Removes the last element from the Vector. | vector<int> myVec = {1, 2, 3}; myVec.pop_back(); // myVec now holds {1, 2} |
insert() | Inserts new elements into the Vector at a specified position. | vector<int> myVec = {1, 3}; myVec.insert(myVec.begin() + 1, 2); // myVec now holds {1, 2, 3} |
erase() | Removes elements from the Vector within a specified range. | vector<int> myVec = {1, 2, 3, 4}; myVec.erase(myVec.begin() + 1, myVec.begin() + 3); // myVec now holds {1, 4} |
swap() | Exchanges the contents of two Vectors. | vector<int> myVec1 = {1, 2, 3}; vector<int> myVec2 = {4, 5, 6}; myVec1.swap(myVec2); // myVec1 now holds {4, 5, 6}, myVec2 holds {1, 2, 3} |
clear() | Removes all elements from the Vector, leaving it empty. | vector<int> myVec = {1, 2, 3}; myVec.clear(); // myVec is now empty |
emplace() | Constructs an element in-place at a specified position in the Vector. | vector<string> myVec = {“hello”}; myVec.emplace(myVec.begin() + 1, “world”); // myVec now holds {“hello”, “world”} |
emplace_back() | Constructs an element in-place at the end of the Vector. | vector<string> myVec; myVec.emplace_back(“hello”); // myVec now holds {“hello”} |
Here is a program that shows the implementation of all the above mentioned functions:
#include <iostream>
#include <vector>
struct Person {
string name;
int age;
Person(string n, int a) : name(move(n)), age(a) {}
};
int main() {
// Creating an empty vector of integers
vector<int> numbers;
// Using assign() to assign values to the vector
numbers.assign({1, 2, 3, 4, 5});
// Using push_back() to add elements to the vector
numbers.push_back(6);
// Using pop_back() to remove the last element
numbers.pop_back();
cout << "Elements in the vector after pop_back(): ";
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
// Using insert() to insert elements at a specific position
numbers.insert(numbers.begin() + 2, 10);
// Using erase() to remove elements at a specific position
numbers.erase(numbers.begin() + 4);
cout << "Elements in the vector after insert() and erase(): ";
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
// Creating another vector
vector<int> anotherNumbers = {7, 8, 9};
// Using swap() to swap the contents of two vectors
numbers.swap(anotherNumbers);
cout << "Elements in the vector after swap(): ";
for (const auto& num : numbers) {
cout << num << " ";
}
cout << endl;
// Using clear() to remove all elements from the vector
anotherNumbers.clear();
// Using emplace() to construct and insert elements at a specific position
vector<Person> persons;
persons.emplace(persons.begin(), "Alice", 25);
persons.emplace_back("Bob", 30);
cout << "Persons in the vector after emplace(): ";
for (const auto& person : persons) {
cout << "(" << person.name << ", " << person.age << ") ";
}
cout << endl;
return 0;
}
Example of Vector in C++
Here is a program that demonstrate working with Vectors in C++:
#include <iostream>
#include <vector>
int main() {
// Creating a vector of integers
vector<int> myVector;
// Adding elements to the vector
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
myVector.push_back(40);
// Accessing elements using index
cout << "Elements in the vector: ";
for (size_t i = 0; i < myVector.size(); ++i) {
cout << myVector[i] << " ";
}
cout << endl;
// Modifying an element at a specific index
myVector[2] = 35;
// Accessing elements using iterators
cout << "Elements in the vector (using iterators): ";
for (auto it = myVector.begin(); it != myVector.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// Removing an element at the end
myVector.pop_back();
// Iterating through the vector using range-based for loop
cout << "Elements in the vector (using range-based for loop): ";
for (const auto& element : myVector) {
cout << element << " ";
}
cout << endl;
return 0;
}
Vector of Vectors in C++ STL
Vector of Vectors is also known as a 2D Vector in C++. It represents a matrix that contains rows and column which stores Vector as an element at every index of matrix. It is similar in structure to a two-dimensional array.
A Vector of Vectors offers a flexible and dynamic way to handle 2D arrays or matrices in C++. It can be resized, accessed, and modified similarly to a 2D array while providing the flexibility of dynamic resizing for each row/column. Here’s an explanation with an example of how we can define a Vector of Vectors:
Example:
A Vector of Vectors can be declared and initialized in various ways. In the example below, we have displayed how we can declare a Vector of Vectors and how we can access the elements in it :
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Declaration of a vector of vectors (2D vector)
vector<vector<int>> matrix;
// Accessing elements in a 2D vector (not initialized in this example)
// matrix[i][j] represents the element at ith row and jth column
return 0;
}
Following program demonstrates how we can initialize a 2D vector:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Initializing a 2D vector with specific size and default values
int rows = 3, cols = 4;
vector<vector<int>> matrix(rows, vector<int>(cols, 0));
// Accessing and modifying elements
matrix[1][2] = 10;
// Displaying elements
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
return 0;
}
Let’s understand the workings of above code:
- Declaration: `vector<vector<int>> matrix;` declares an empty 2D Vector `matrix`.
- Initialization: `vector<vector<int>> matrix(rows, vector<int>(cols, 0));` initializes a 2D Vector `matrix` with `rows` defining number of rows and `cols` defining number of columns, each element initialized to `0`.
- Accessing Elements: Elements in the 2D Vector are accessed and modified using double indexing (`matrix[i][j]`).
- The initialized 2D Vector `matrix` is traversed using nested loops to display its elements.
Advantages of Vectors
Vectors in C++ provide several advantages that make them a versatile and popular choice for dynamic arrays. Here are the followings:
Dynamic Resizing: Vectors can dynamically resize themselves. Vectors can automatically adjust their capacity as elements are added or removed. This eliminates the need for manual memory management and allows flexible storage allocation.
Range-Based For Loops: Vectors support range-based for loops, simplifying iteration through elements without explicit indexing or iterators.
Standard Library Functionality: Vectors are part of the C++ Standard Template Library (STL) and come with various built-in functions (e.g., `push_back()`, `pop_back()`, `size()`, `empty()`) for easy manipulation and management.
Versatility: Vectors support various data types (`int`, `double`, `string`, custom objects, etc.), making them suitable for diverse applications.
Compatible with Algorithms: Vectors seamlessly integrate with STL algorithms like sorting, searching, and manipulation functions (`sort()`, `find()`, `copy()`, etc.).
Check out our YouTube video on C programming language for the absolute beginners:
Conclusion
Vectors are much better than arrays and linked lists due to their dynamic nature, adaptable sizing, and ease of data manipulation. Their flexibility in adjusting size, efficient copying methods, simplicity in passing as arguments, and multiple-member functions make them a superior choice for managing variable-sized data. With convenient initialization and automatic memory-clearing abilities, Vector is an optimal solution for handling extensive and evolving data structures in programs.