Vectors in C++
std::vector
is one of the most commonly used containers in C++ because it provides a dynamic array that can grow and shrink as needed. Here's a detailed explanation of the various functions and operations associated with std::vector
:
1. Creating a Vector
std::vector<int> vec; // Creates an empty vector of integers
std::vector<int> vec(5); // Creates a vector of size 5 with default-initialized elements (0 for int)
std::vector<int> vec(5, 10); // Creates a vector of size 5 with all elements initialized to 10
std::vector<int> vec = {1, 2, 3, 4, 5}; // Creates and initializes a vector using an initializer list
2. Accessing Elements
operator[]
: Accesses the element at the specified index. No bounds checking.at()
: Accesses the element at the specified index with bounds checking.front()
: Returns a reference to the first element.back()
: Returns a reference to the last element.
std::vector<int> vec = {1, 2, 3};
int a = vec[1]; // a = 2
int b = vec.at(1); // b = 2
int first = vec.front(); // first = 1
int last = vec.back(); // last = 3
3. Modifying the Vector
push_back()
: Adds an element to the end of the vector.pop_back()
: Removes the last element from the vector.insert()
: Inserts elements at a specified position.erase()
: Removes elements from a specified position or range.clear()
: Removes all elements from the vector.resize()
: Resizes the vector to the specified size.assign()
: Assigns new values to the vector.
std::vector<int> vec = {1, 2, 3};
vec.push_back(4); // vec becomes {1, 2, 3, 4}
vec.pop_back(); // vec becomes {1, 2, 3}
vec.insert(vec.begin() + 1, 5); // vec becomes {1, 5, 2, 3}
vec.erase(vec.begin() + 1); // vec becomes {1, 2, 3}
vec.resize(5, 10); // vec becomes {1, 2, 3, 10, 10}
vec.clear(); // vec becomes empty
vec.assign(3, 7); // vec becomes {7, 7, 7}
4. Size and Capacity
size()
: Returns the number of elements in the vector.capacity()
: Returns the number of elements that the vector can hold before needing to allocate more memory.empty()
: Checks whether the vector is empty.reserve()
: Requests that the vector capacity be at least enough to contain a specified number of elements.shrink_to_fit()
: Reduces the capacity of the vector to fit its size.
std::vector<int> vec = {1, 2, 3};
size_t sz = vec.size(); // sz = 3
size_t cap = vec.capacity(); // cap >= 3
bool isEmpty = vec.empty(); // isEmpty = false
vec.reserve(10); // vec's capacity becomes at least 10
vec.shrink_to_fit(); // reduces the capacity to size
5. Iterators
begin()
: Returns an iterator to the first element.end()
: Returns an iterator to the element following the last element.rbegin()
: Returns a reverse iterator to the last element.rend()
: Returns a reverse iterator to the element preceding the first element.
std::vector<int> vec = {1, 2, 3};
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " "; // Output: 1 2 3
}
for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
std::cout << *it << " "; // Output: 3 2 1
}
6. Swapping
swap()
: Exchanges the contents of two vectors.
std::vector<int> vec1 = {1, 2};
std::vector<int> vec2 = {3, 4};
vec1.swap(vec2); // vec1 becomes {3, 4}, vec2 becomes {1, 2}
7. Comparison Operators
==
,!=
,<
,<=
,>
,>=
: These operators compare two vectors lexicographically.
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = {1, 2, 4};
bool isEqual = (vec1 == vec2); // isEqual = false
bool isLess = (vec1 < vec2); // isLess = true (because 3 < 4)
8. Data Access
data()
: Returns a direct pointer to the memory array used internally by the vector.
std::vector<int> vec = {1, 2, 3};
int* p = vec.data();
std::cout << p[0] << " " << p[1] << " " << p[2]; // Output: 1 2 3
9. Emplace Functions
emplace_back()
: Constructs and inserts an element at the end of the vector.emplace()
: Constructs and inserts an element at the specified position.
std::vector<std::pair<int, int>> vec;
vec.emplace_back(1, 2); // vec contains {(1, 2)}
std::vector<int> vec2 = {1, 3};
vec2.emplace(vec2.begin() + 1, 2); // vec2 becomes {1, 2, 3}
10. Copying and Moving Vectors
Copy Constructor: Creates a new vector as a copy of an existing one.
Move Constructor: Transfers the contents of one vector to another without copying.
std::vector<int> vec1 = {1, 2, 3};
std::vector<int> vec2 = vec1; // Copy constructor
std::vector<int> vec3 = std::move(vec1); // Move constructor (vec1 is now empty)
11. Non-Member Functions
std::swap()
: Swaps the contents of two vectors.std::begin()
,std::end()
: Returns iterators to the beginning and end of the vector, respectively.
std::vector<int> vec1 = {1, 2};
std::vector<int> vec2 = {3, 4};
std::swap(vec1, vec2); // vec1 becomes {3, 4}, vec2 becomes {1, 2}
for (auto it = std::begin(vec1); it != std::end(vec1); ++it) {
std::cout << *it << " "; // Output: 3 4
}
12. Capacity Functions
max_size()
: Returns the maximum number of elements the vector can hold.
std::vector<int> vec;
size_t maxSize = vec.max_size(); // Returns the maximum possible size of the vector
Summary
std::vector
is extremely versatile and can handle a wide range of use cases with its rich set of functions. Understanding these functions and how to use them efficiently can make a big difference in the performance and readability of your code, especially in competitive programming where time is of the essence.