Vectors
Vectors are dynamic arrays that can resize themselves automatically when elements are added or removed. They are one of the most commonly used containers in C++ and provide the flexibility of dynamic memory allocation with the performance benefits of contiguous memory storage.
The C++ Standard Template Library (STL) provides a powerful vector class that handles memory management automatically, making it safer and more convenient than manual dynamic arrays while maintaining excellent performance.
Vector Basics
Vectors can be initialized in multiple ways and support various data types:
Creating and Initializing Vectors
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Different ways to create vectors
vector<int> numbers1; // Empty vector
vector<int> numbers2(5); // 5 elements, all initialized to 0
vector<int> numbers3(5, 10); // 5 elements, all initialized to 10
vector<int> numbers4 = {1, 2, 3, 4, 5}; // Initialize with values
vector<int> numbers5(numbers4); // Copy constructor
// Display vector contents
cout << "numbers1 (empty): ";
for (int num : numbers1) cout << num << " ";
cout << "Size: " << numbers1.size() << endl;
cout << "numbers2 (5 zeros): ";
for (int num : numbers2) cout << num << " ";
cout << "Size: " << numbers2.size() << endl;
cout << "numbers3 (5 tens): ";
for (int num : numbers3) cout << num << " ";
cout << "Size: " << numbers3.size() << endl;
cout << "numbers4 (1-5): ";
for (int num : numbers4) cout << num << " ";
cout << "Size: " << numbers4.size() << endl;
// Vector of strings
vector<string> fruits = {"apple", "banana", "orange"};
cout << "\nFruits: ";
for (const string& fruit : fruits) {
cout << fruit << " ";
}
cout << endl;
return 0;
}Adding and Removing Elements
Vectors automatically resize when needed. Common operations include push_back(), insert(), pop_back(), and erase():
Dynamic Resizing Operations
#include <iostream>
#include <vector>
using namespace std;
void printVector(const vector<int>& vec, const string& label) {
cout << label << ": ";
for (int val : vec) cout << val << " ";
cout << "(size: " << vec.size() << ", capacity: " << vec.capacity() << ")" << endl;
}
int main() {
vector<int> numbers;
cout << "=== Adding Elements ===" << endl;
printVector(numbers, "Initial");
// Adding elements to the end
numbers.push_back(10);
printVector(numbers, "After push_back(10)");
numbers.push_back(20);
numbers.push_back(30);
printVector(numbers, "After adding 20, 30");
// Insert at specific position
numbers.insert(numbers.begin() + 1, 15);
printVector(numbers, "After insert 15 at index 1");
cout << "\n=== Removing Elements ===" << endl;
// Remove last element
numbers.pop_back();
printVector(numbers, "After pop_back()");
// Remove at specific position
numbers.erase(numbers.begin() + 1);
printVector(numbers, "After erasing index 1");
// Clear all elements
numbers.clear();
printVector(numbers, "After clear");
return 0;
}Vector Iterators
Iterators provide a way to traverse through vector elements and are essential for many STL algorithms:
Using Iterators
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> numbers = {5, 2, 8, 1, 9, 3};
// Using iterators to traverse
cout << "Forward iteration: ";
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
cout << *it << " ";
}
cout << endl;
// Reverse iteration
cout << "Reverse iteration: ";
for (auto it = numbers.rbegin(); it != numbers.rend(); ++it) {
cout << *it << " ";
}
cout << endl;
// Using algorithms with iterators
sort(numbers.begin(), numbers.end());
cout << "After sorting: ";
for (int num : numbers) cout << num << " ";
cout << endl;
// Find element
auto found = find(numbers.begin(), numbers.end(), 5);
if (found != numbers.end()) {
cout << "Found 5 at position: " << distance(numbers.begin(), found) << endl;
}
return 0;
}Performance Considerations
Understanding vector performance characteristics helps write efficient code:
- Random access: O(1) - accessing elements by index is constant time
- Insertion/deletion at end: O(1) amortized - push_back and pop_back are very efficient
- Insertion/deletion at middle: O(n) - requires shifting elements
- Memory: Contiguous storage provides cache-friendly access patterns