Dynamic array class template, which is declared in the corresponding header file from the standard library, provides its own memory management. In contrast to C-style arrays or fixed-size standard arrays, which need to know the size of the array at compile time, a vector can resize itself dynamically as elements are inserted or removed. It keeps its elements in contiguous memory positions. Thus, elements can be addressed by offsetting and the collection is very cache-friendly.
#include <iostream>
#include <vector>
int main() {
// Initialize a vector of integers with four elements
std::vector<int> numbers{ 10, 20, 30, 40 };
// Iterate and print the elements
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << "\n";
return 0;
}
In order to access elements stored in a vector you can use either the subscript operator or the bounds-checked member function. Subscript operator doesn't check the validity of index passed to it. So it is fast but unsafe because if an invalid index is used then it leads to undefined behavior. Bounds-checked function checks the validity of the index against the range of the vector. If the index is invalid then the out-of-range exception is thrown and it prevents unauthorized memory access and catches some bugs during run-time.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> items{ 100, 200, 300 };
// Fast access without bounds checking
std::cout << "First item: " << items[0] << "\n";
// Bounds-checked access with a valid index
std::cout << "Third item: " << items.at(2) << "\n";
return 0;
}
#include <iostream>
#include <vector>
int main() {
std::vector<int> values;
// Add elements dynamically
values.push_back(5);
values.push_back(10);
values.push_back(15);
std::cout << "Size after pushes: " << values.size() << "\n";
// Remove the last element
values.pop_back();
std::cout << "Size after pop: " << values.size() << "\n";
// Clear all elements
values.clear();
if (values.empty()) {
std::cout << "Vector is now empty\n";
}
return 0;
}
In order to allocate memory efficiently vector differentiates between two parameters – its size and its capacity. Size is the number of elements stored in a vector. Capacity is the total number of elements that can be stored in the vector's currently allocated memory block without reallocation of a larger memory block. If you add an element and it exceeds the capacity, the vector performs the following steps – allocates a larger block of memory, moves/copies existing elements to the new location, destroys existing elements and deallocates the previous memory block.
#include <iostream>
#include <vector>
int main() {
std::vector<int> list;
for (int i = 0; i < 5; ++i) {
list.push_back(i);
std::cout << "Size: " << list.size()
<< ", Capacity: " << list.capacity() << "\n";
}
return 0;
}
Since allocation of the new heap memory and moving elements during reallocation is an expensive operation you can optimize your program using reservation member function. If you know the number of elements the vector will hold you can allocate a specified number of memory in advance using this function. It guarantees that the vector will not need any reallocations when adding elements, until the reserved limit. Remember that the reserved memory changes capacity of the vector but not its size and initializes no elements.#include <iostream>
#include <vector>
int main() {
std::vector<int> optimized_list;
// Pre-allocate memory for 100 elements
optimized_list.reserve(100);
std::cout << "Size: " << optimized_list.size()
<< ", Capacity: " << optimized_list.capacity() << "\n";
// These pushes will not trigger any reallocations
optimized_list.push_back(1);
optimized_list.push_back(2);
return 0;
}
Exercise: std::vectorStarter code, hints and solutionOpenClose
Practice: std::vector
Work through the mission, reveal hints only when needed, and compare your result with the model solution.
Your challenge
Push 20 before the first size report. Predict the sizes after pushing, popping, and clearing, and identify which element pop_back removes.
Mission checklist
- Run the starter as a baseline, then predict the change requested in Your challenge.
- Make that change in your editor; use the lesson-specific hints if you need help.
- Compile and run your answer, then compare with the worked solution and explain the result.
Starter program
This is the working baseline, not the completed answer. Compile as C++20, then make the change described above.
#include <iostream>
#include <vector>
int main() {
std::vector<int> values;
// Add elements dynamically
values.push_back(5);
values.push_back(10);
values.push_back(15);
std::cout << "Size after pushes: " << values.size() << "\n";
// Remove the last element
values.pop_back();
std::cout << "Size after pop: " << values.size() << "\n";
// Clear all elements
values.clear();
if (values.empty()) {
std::cout << "Vector is now empty\n";
}
return 0;
}Hints
Each push_back adds one element at the end, while pop_back removes the last element. Follow the size through those operations before clear runs.
Insert another push_back before the first size output and update both size predictions. clear removes all elements; empty then reports whether size is zero.
Worked solution
push_back(20) adds a fourth element. The first size becomes 4, pop_back removes that last element and leaves size 3, and clear still empties the vector.
#include <iostream>
#include <vector>
int main() {
std::vector<int> values;
// Add elements dynamically
values.push_back(5);
values.push_back(10);
values.push_back(15);
values.push_back(20);
std::cout << "Size after pushes: " << values.size() << "\n";
// Remove the last element
values.pop_back();
std::cout << "Size after pop: " << values.size() << "\n";
// Clear all elements
values.clear();
if (values.empty()) {
std::cout << "Vector is now empty\n";
}
return 0;
}
Example output
Size after pushes: 4
Size after pop: 3
Vector is now empty
0 comments
No comments yet. Be the first.