Vector Container in C++: Usage and Operations
In C++, the vector
container is part of the Standard Template Library (STL) and is one of the most widely used data structures. It provides dynamic resizing and allows random access to elements. Vectors are particularly useful when you need to store a collection of items that can grow or shrink in size and when you want to access elements by their index quickly.
In this guide, we will cover everything you need to know about the vector
container, including how to construct vectors, how to perform common operations, and how to take full advantage of its capabilities in C++.
Table of Contents
- Introduction to Vector in C++
- Different Ways to Construct a Vector
-
Common Operations on Vector
push_back()
pop_back()
insert()
erase()
at()
size()
empty()
clear()
- Working with Custom Data Types
- Iterators in Vectors
- Vector of Vectors
- Summary and Best Practices
1. Introduction to Vector in C++
A vector in C++ is a dynamic array that can grow or shrink in size. Unlike arrays, which have a fixed size, vectors manage their size dynamically, providing flexibility when handling collections of data. It supports random access, meaning you can directly access any element in constant time, which makes vectors efficient for many operations.
Key Features:
- Dynamic Sizing: Vectors can grow or shrink dynamically as elements are added or removed.
- Random Access: Vectors support constant time access to any element using indices.
- Contiguous Memory Allocation: Like arrays, elements in a vector are stored in contiguous memory locations, providing cache efficiency.
-
Efficient Insertion/Deletion at the End: Vectors can efficiently add or remove elements at the end with
push_back()
andpop_back()
, respectively.
2. Different Ways to Construct a Vector
The vector
class in C++ can be constructed in multiple ways depending on the desired behavior.
2.1 Default Constructor
You can create an empty vector using the default constructor.
vector<int> v;
This creates an empty vector of integers, and you can add elements later.
2.2 Constructor with Initial Size
You can create a vector with a specific size, where each element is initialized to the default value for the element type.
vector<int> v(5); // Creates a vector of size 5 with default-initialized elements (0 for int)
If you want to initialize the elements to a specific value, you can provide a second argument.
vector<int> v(5, 10); // Creates a vector of size 5 with each element initialized to 10
2.3 Constructor with an Initializer List
You can initialize a vector directly with a list of values.
vector<int> v = {1, 2, 3, 4, 5};
This creates a vector containing the values 1, 2, 3, 4, and 5.
2.4 Constructor with Another Container
You can also create a vector by copying the contents of another container (like another vector or array).
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2(v1); // Creates a vector that is a copy of v1
2.5 Constructor with Iterators
You can initialize a vector using a range of iterators from another container. Note that you cannot directly pass containers like deque
or list
to the vector
constructor, but you can use their iterators (.begin()
and .end()
) to initialize the vector.
vector<int> v(v1.begin(), v1.end()); // Initializes a vector using iterators from another vector
You can also use iterators from other containers like deque
or list
to initialize a vector, as shown below:
deque<int> d = {1, 2, 3, 4, 5};
vector<int> v(d.begin(), d.end()); // Initializes a vector using iterators from a deque
list<int> l = {10, 20, 30};
vector<int> v2(l.begin(), l.end()); // Initializes a vector using iterators from a list
However, note that you cannot directly pass the entire deque
or list
container to the vector constructor; you must use .begin()
and .end()
to specify the range.
Similarly, you can use iterators from arrays. To initialize a vector from an array, you can use the array's beginning and ending pointers. For example, if you have an array like arr
:
int arr[] = {1, 2, 3, 4, 5};
vector<int> v(arr, arr + 5); // Initializes a vector using pointers to an array
In this case, arr
is the array, and arr + 5
specifies the range of elements to be used from the array (from the start to the fifth element, exclusive). This way, you can initialize the vector directly from an array.
2.6 Assignment Operator
You can use the assignment operator to copy elements from one vector to another.
vector<int> v1 = {1, 2, 3};
vector<int> v2;
v2 = v1; // Now v2 contains the same elements as v1
The assignment operator performs a deep copy, meaning that the elements of v1
are copied into v2
, not just the pointer or reference.
3. Common Operations on Vector
3.1 push_back()
The push_back()
function adds an element to the end of the vector. This operation is amortized constant time.
Syntax:
v.push_back(element);
Example:
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
After this, the vector v
will contain: [10, 20, 30]
.
3.2 pop_back()
The pop_back()
function removes the last element from the vector. This operation is constant time.
Syntax:
v.pop_back();
Example:
vector<int> v = {10, 20, 30};
v.pop_back(); // Removes 30
After calling pop_back()
, the vector will contain: [10, 20]
.
3.3 insert()
The insert()
function allows you to insert an element at a specific position in the vector. It can be used to insert a single element or multiple elements at once. Additionally, you can insert a range of elements or elements from another container, such as a vector.
Syntax:
- Insert a single element:
v.insert(position, element);
- Insert multiple identical elements:
v.insert(position, count, element);
- Insert elements from another container (e.g., vector, list):
v.insert(position, container.begin(), container.end());
Example 1: Insert a Single Element
vector<int> v = {10, 20, 30};
v.insert(v.begin() + 1, 15); // Inserts 15 at position 1
After this, the vector v
will contain: [10, 15, 20, 30]
.
Example 2: Insert Multiple Identical Elements
v.insert(v.begin() + 2, 3, 100); // Inserts three 100's starting from position 2
After this, the vector v
will contain: [10, 15, 100, 100, 100, 20, 30]
.
Example 3: Insert Elements from Another Vector
vector<int> v1 = {1, 2, 3};
vector<int> v2 = {4, 5, 6};
v1.insert(v1.end(), v2.begin(), v2.end()); // Inserts all elements from v2 at the end of v1
After this, the vector v1
will contain: [1, 2, 3, 4, 5, 6]
.
3.4 erase()
The erase()
function removes elements from the vector at a specified position or a range of positions. Similar to insert()
, erase()
can be used to remove a single element, multiple elements, or a range of elements.
Syntax:
- Erase a single element:
v.erase(position);
- Erase a range of elements:
v.erase(start, end); // Removes elements from start to end-1
Example 1: Erase a Single Element
vector<int> v = {10, 20, 30};
v.erase(v.begin() + 1); // Removes element at position 1 (20)
After this, the vector v
will contain: [10, 30]
.
Example 2: Erase a Range of Elements
vector<int> v = {10, 20, 30, 40, 50};
v.erase(v.begin() + 1, v.begin() + 4); // Removes elements from position 1 to 3 (20, 30, 40)
After this, the vector v
will contain: [10, 50]
.
3.5 at()
The at()
function retrieves an element at a specified index with bounds checking. If the index is out of bounds, it throws an out_of_range
exception.
Syntax:
element = v.at(index);
Example:
vector<int> v = {10, 20, 30};
cout << v.at(1) << endl; // Outputs: 20
3.6 size()
The size()
function returns the number of elements in the vector.
Syntax:
size_t size = v.size();
Example:
vector<int> v = {10, 20, 30};
cout << "Size of vector: " << v.size() << endl; // Outputs: 3
3.7 empty()
The empty()
function checks whether the vector is empty.
Syntax:
bool isEmpty = v.empty();
Example:
vector<int> v;
cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << endl; // Outputs: Yes
v.push_back(10);
cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << endl; // Outputs: No
3.8 clear()
The clear()
function removes all elements from the vector.
Syntax:
v.clear();
Example:
vector<int> v = {10, 20, 30};
v.clear(); // Removes all elements
After calling clear()
, the vector will be empty.
4. Working with Custom Data Types
Vectors can also store custom data types such as classes or structs. When working with custom types, remember to define appropriate constructors, destructors, and operators if necessary.
Example:
class Student {
public:
string name;
int age;
Student(string n, int a) : name(n), age(a) {}
};
vector<Student> students;
students.push_back(Student("John", 20));
students.push_back(Student("Alice", 22));
5. Iterators in Vectors
Vectors support iterators that allow you to iterate over the elements in a way similar to arrays but with more flexibility. The begin()
and end()
functions return iterators pointing to the first and one-past-the-last elements of the vector, respectively.
5.1 Example Using Iterators
vector<int> v = {10, 20, 30};
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // Output: 10 20 30
}
6. Vector of Vectors
A vector can hold other vectors, allowing you to create a matrix-like structure.
Example:
vector<vector<int>> matrix = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
You can access elements with two indices:
cout << matrix[0][1] << endl; // Outputs: 2
7. Summary and Best Practices
- Vectors are a powerful and flexible container in C++ for managing dynamic arrays.
- Always use
push_back()
to add elements to the end andpop_back()
to remove elements. - If you know the size in advance, consider using
reserve()
to reduce reallocations. - Be mindful of the costs of inserting and erasing elements in the middle of the vector, as these operations may shift many elements.
- Vectors are great when you need random access and efficient resizing but may not be the best choice for frequent insertions/deletions at the front.
By understanding and leveraging vectors in C++, you can efficiently handle dynamic collections and improve the performance and flexibility of your programs.
Top comments (0)