Vector i per C++

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 31

Vector in C++ STL

Vectors are the same as dynamic arrays with the ability to resize themselves automatically when
an element is inserted or deleted, with their storage being handled automatically by the container.
Vector elements are placed in contiguous storage so that they can be accessed and traversed
using iterators.
In vectors, data is inserted at the end. Inserting at the end takes differential time, as sometimes
the array may need to be extended. Removing the last element takes only constant time because
no resizing happens. Inserting and erasing at the beginning or in the middle is linear in time.

What is vector in C++?

vector in C++ is the class template that contains the vector container and its member functions.
It is defined inside the <vector> header file. The member functions of the vector class provide
various functionalities to vector containers.

Key Characteristics of Vectors


 Dynamic Sizing: Vectors automatically resize when you add or remove elements. This
flexibility is one of the main reasons vectors are preferred over traditional arrays in many
situations.
 Efficient Access: Since vector elements are stored in contiguous memory locations, you can
access elements in constant time using their index, similar to arrays.
 Insertion and Deletion: Insertion of elements is typically done at the end of the vector,
where it operates in constant time. However, inserting or deleting elements at the beginning
or middle of the vector takes linear time due to the need to shift elements
Syntax to Declare Vector in C++

vector<dataType> vectorName;

where the data type is the type of data of each element of the vector. You can remove the if you
have already used the std namespace.
Initialization of Vector in C++
We can initialize a vector in the following ways:
1. Initialization Using List
This initialization is done with a declaration. Here, we pass the list of elements to the vector
constructor to create a vector with the specified elements.

vector<dataType> name({ value1, value2, value3 ....});

2. Initialization With a Single Value


This initialization is also done with declaration. Here, we specify the size of the vector and then
initialize every element of the vector with the value.
vector<dataType> name(size, value);
3. Initialization From Another Vector
This initialization is used to create a vector that is an exact copy of other_vec.
vector<dataType> name(other_vec);
8 Ways to Initialize Vector in C++
Initializing a vector means assigning some initial values to the vector elements. In this article, we
will learn 8 different ways to initialize a vector in C++.
Table of Content
 Using Initializer List
 One by One Initialization
 With a Single Value
 From an Array
 From Another Vector
 From Any STL Container
 Using fill() Function

all eight ways to initialize a vector:

#include <iostream>
#include <vector>

int main() {
// 1. Default Initialization
vector<int> vec1; // Creates an empty vector
cout << "Default Initialization (vec1): Size = " << vec1.size() << endl; // Output: 0

// 2. Initialize with Specific Size


vector<int> vec2(5); // Creates a vector with 5 elements, all initialized to 0
cout << "Initialize with Specific Size (vec2): ";
for (int val : vec2) {
cout << val << " "; // Output: 0 0 0 0 0
}
cout << endl;

// 3. Initialize with Size and Default Value


vector<int> vec3(5, 10); // Creates a vector with 5 elements, all initialized to 10
cout << "Initialize with Size and Default Value (vec3): ";
for (int val : vec3) {
cout << val << " "; // Output: 10 10 10 10 10
}
cout << endl;

// 4. Initialize Using an Array


int arr[] = {1, 2, 3, 4, 5};
vector<int> vec4(arr, arr + 5); // Initializes vector with array elements
cout << "Initialize Using an Array (vec4): ";
for (int val : vec4) {
cout << val << " "; // Output: 1 2 3 4 5
}
cout << endl;

// 5. Initialize Using an Initializer List


vector<int> vec5 = {1, 2, 3, 4, 5}; // Initializes with specified values
cout << "Initialize Using an Initializer List (vec5): ";
for (int val : vec5) {
cout << val << " "; // Output: 1 2 3 4 5
}
cout << endl;

// 6. Copy Constructor
vector<int> vec6(vec5); // Copies elements from 'vec5'
cout << "Copy Constructor (vec6): ";
for (int val : vec6) {
cout << val << " "; // Output: 1 2 3 4 5
}
cout << endl;

// 7. Using assign() Method


vector<int> vec7;
vec7.assign(5, 20); // Assigns 5 elements, each with the value 20
cout << "Using assign() Method (vec7): ";
for (int val : vec7) {
cout << val << " "; // Output: 20 20 20 20 20
}
cout << endl;

// 8. Range Initialization
vector<int> vec8(vec5.begin() + 1, vec5.end() - 1); // Initializes with elements from index 1 to
3
cout << "Range Initialization (vec8): ";
for (int val : vec8) {
cout << val << " "; // Output: 2 3 4
}
cout << endl;

return 0;
}

Explanation
 vec1: Demonstrates Default Initialization, creating an empty vector.
 vec2: Demonstrates Initialization with Specific Size, creating a vector of size 5 with all
elements initialized to 0.
 vec3: Demonstrates Initialization with Size and Default Value, creating a vector of size
5 with all elements initialized to 10.
 vec4: Demonstrates Initialization Using an Array, initializing a vector with the
elements of an array.
 vec5: Demonstrates Initialization Using an Initializer List, initializing with specified
values.
 vec6: Demonstrates Copy Constructor, copying the contents of vec5.
 vec7: Demonstrates Using assign() Method, assigning 5 elements with the value 20.
 vec8: Demonstrates Range Initialization, initializing a vector with a subset of elements
from vec5.

Commonly Used Member Functions


Some commonly used member functions of vector class are written below:
Iterators
1. begin() – Returns an iterator pointing to the first element in the vector
2. end() – Returns an iterator pointing to the theoretical element that follows the last element in
the vector
3. rbegin() – Returns a reverse iterator pointing to the last element in the vector (reverse
beginning). It moves from last to first element
4. rend() – Returns a reverse iterator pointing to the theoretical element preceding the first
element in the vector (considered as reverse end)
5. cbegin() – Returns a constant iterator pointing to the first element in the vector.
6. cend() – Returns a constant iterator pointing to the theoretical element that follows the last
element in the vector.
7. crbegin() – Returns a constant reverse iterator pointing to the last element in the vector
(reverse beginning). It moves from last to first element
8. crend() – Returns a constant reverse iterator pointing to the theoretical element preceding the
first element in the vector (considered as reverse end)
Example:

demonstrating the use of each of these iterator functions in C++:

#include <iostream>
#include <vector>
using namespace std;

int main() {
// Initialize a vector with some values
vector<int> vec = {10, 20, 30, 40, 50};

// 1. begin() - Iterator pointing to the first element


cout << "Using begin(): " << *vec.begin() << endl;
// 2. end() - Iterator pointing to the element after the last one
cout << "Using end(): ";
for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;

// 3. rbegin() - Reverse iterator pointing to the last element


cout << "Using rbegin(): " << *vec.rbegin() << endl;

// 4. rend() - Reverse iterator pointing to the element before the first


cout << "Using rend(): ";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
cout << *rit << " ";
}
cout << endl;

// 5. cbegin() - Constant iterator pointing to the first element


cout << "Using cbegin(): " << *vec.cbegin() << endl;

// 6. cend() - Constant iterator pointing to the element after the last


one
cout << "Using cend(): ";
for (auto it = vec.cbegin(); it != vec.cend(); ++it) {
cout << *it << " ";
}
cout << endl;

// 7. crbegin() - Constant reverse iterator pointing to the last element


cout << "Using crbegin(): " << *vec.crbegin() << endl;

// 8. crend() - Constant reverse iterator pointing to the element before


the first
cout << "Using crend(): ";
for (auto rit = vec.crbegin(); rit != vec.crend(); ++rit) {
cout << *rit << " ";
}
cout << endl;

return 0;
}

Explanation :

1. begin(): Returns an iterator pointing to the first element. Using *vec.begin(), we can
dereference it to get the first element.
o Output: Using begin(): 10
2. end(): Returns an iterator pointing to the element after the last one. This iterator is
commonly used in loops to iterate over all elements.
o Output: Using end(): 10 20 30 40 50
3. rbegin(): Returns a reverse iterator pointing to the last element. We can use this to iterate
backward.
o Output: Using rbegin(): 50
4. rend(): Returns a reverse iterator pointing to the element before the first one. We use it to
iterate backward from rbegin() to rend().
o Output: Using rend(): 50 40 30 20 10
5. cbegin(): Returns a constant iterator pointing to the first element. It ensures that elements
cannot be modified via this iterator.
o Output: Using cbegin(): 10
6. cend(): Returns a constant iterator pointing to the element after the last one. It is used in a
loop to ensure elements are not modified.
o Output: Using cend(): 10 20 30 40 50
7. crbegin(): Returns a constant reverse iterator pointing to the last element. It ensures
elements are not modified when iterating backward.
o Output: Using crbegin(): 50
8. crend(): Returns a constant reverse iterator pointing to the element before the first one. It
is used to iterate backward in a read-only manner.
o Output: Using crend(): 50 40 30 20 10

This example covers each of the iterator types and shows how they are used to access or traverse
the elements in a vector.

-----
Capacity
1. size() – Returns the number of elements in the vector.
2. max_size() – Returns the maximum number of elements that the vector can hold.
3. capacity() – Returns the size of the storage space currently allocated to the vector expressed
as number of elements.
4. resize(n) – Resizes the container so that it contains ‘n’ elements.
5. empty() – Returns whether the container is empty.
6. shrink_to_fit() – Reduces the capacity of the container to fit its size and destroys all elements
beyond the capacity.
7. reserve() – Requests that the vector capacity be at least enough to contain n elements.

the use of each of these methods in a vector:

example
#include <iostream>
#include <vector>

int main() {
// Initialize a vector with some elements
vector<int> vec = {10, 20, 30, 40, 50};

// 1. size() - Returns the number of elements in the vector


cout << "Size: " << vec.size() << endl; // Output: 5

// 2. max_size() - Returns the maximum number of elements the vector can


hold
cout << "Max Size: " << vec.max_size() << endl;
// 3. capacity() - Returns the size of the storage space allocated for the
vector
cout << "Capacity: " << vec.capacity() << endl;

// 4. resize(n) - Resizes the vector to contain 'n' elements


vec.resize(3); // Reduces the size to 3 elements
cout << "After resizing to 3: ";
for (int val : vec) {
cout << val << " "; // Output: 10 20 30
}
cout << endl;

vec.resize(6, 100); // Increases size to 6, new elements initialized to


100
cout << "After resizing to 6 with default value 100: ";
for (int val : vec) {
cout << val << " "; // Output: 10 20 30 100 100 100
}
cout << endl;

// 5. empty() - Returns whether the vector is empty


cout << "Is the vector empty? " << (vec.empty() ? "Yes" : "No") <<
endl; // Output: No

// 6. shrink_to_fit() - Reduces capacity to fit the size of the vector


cout << "Capacity before shrink_to_fit: " << vec.capacity() << endl;
vec.shrink_to_fit();
cout << "Capacity after shrink_to_fit: " << vec.capacity() << endl;

// 7. reserve(n) - Requests that the vector capacity be at least enough to


contain 'n' elements
vec.reserve(10); // Requests the capacity to be at least 10
cout << "Capacity after reserve(10): " << vec.capacity() << endl;

return 0;
}

Explanation of Each Method

1. size(): Returns the current number of elements in the vector.


o Output: Size: 5
2. max_size(): Returns the theoretical maximum number of elements the vector can hold.
This depends on the system and compiler.
o Output: Max Size: <large value> (This value can be quite large and is specific to
your environment)
3. capacity(): Returns the total number of elements that the vector can hold without needing
to reallocate memory.
o Output: Capacity: <initial capacity> (The initial capacity may vary)
4. resize(n): Changes the number of elements in the vector.
o vec.resize(3): Reduces the vector size to 3 elements.
o vec.resize(6, 100): Increases the vector size to 6, initializing new elements with
100.
5. empty(): Checks if the vector is empty.
o Output: Is the vector empty? No
6. shrink_to_fit(): Reduces the vector's capacity to match its current size, freeing up unused
memory.
o Output: Capacity before and after calling shrink_to_fit() may differ.
7. reserve(n): Increases the capacity of the vector to at least n elements. If n is less than the
current capacity, the capacity is unchanged.
o Output: The capacity after reserve(10) will be at least 10.

------
Element access
1. reference operator [g] – Returns a reference to the element at position ‘g’ in the vector
2. at(g) – Returns a reference to the element at position ‘g’ in the vector
3. front() – Returns a reference to the first element in the vector
4. back() – Returns a reference to the last element in the vector
5. data() – Returns a direct pointer to the memory array used internally by the vector to store its
owned elements.

each of these methods with a vector:

#include <iostream>
#include <vector>

int main() {
// Initialize a vector with some values
vector<int> vec = {10, 20, 30, 40, 50};

// 1. Reference operator [g] - Returns a reference to the element at


position 'g'
cout << "Element at index 2 using []: " << vec[2] << endl; // Output: 30
vec[2] = 35; // Modifying the element at index 2
cout << "Modified element at index 2: " << vec[2] << endl; // Output: 35

// 2. at(g) - Returns a reference to the element at position 'g' with


bounds checking
cout << "Element at index 3 using at(): " << vec.at(3) << endl; // Output:
40
vec.at(3) = 45; // Modifying the element at index 3
cout << "Modified element at index 3: " << vec.at(3) << endl; // Output:
45

// 3. front() - Returns a reference to the first element in the vector


cout << "First element using front(): " << vec.front() << endl; // Output:
10
vec.front() = 5; // Modifying the first element
cout << "Modified first element: " << vec.front() << endl; // Output: 5

// 4. back() - Returns a reference to the last element in the vector


cout << "Last element using back(): " << vec.back() << endl; // Output: 50
vec.back() = 55; // Modifying the last element
cout << "Modified last element: " << vec.back() << endl; // Output: 55
// 5. data() - Returns a direct pointer to the memory array used
internally by the vector
int* ptr = vec.data();
cout << "Elements using data(): ";
for (size_t i = 0; i < vec.size(); ++i) {
cout << *(ptr + i) << " "; // Accessing elements using the pointer
}
cout << endl; // Output: 5 20 35 45 55

return 0;
}

Explanation of Each Method

6. Reference Operator []: Returns a reference to the element at position g in the vector.
1. Usage: vec[2] accesses the element at index 2. It also allows modification of that
element.
2. Output: Element at index 2 using []: 30, then modifies the value and prints
Modified element at index 2: 35.
7. at(g): Returns a reference to the element at position g in the vector with bounds checking.
If g is out of bounds, an exception is thrown.
1. Usage: vec.at(3) accesses and modifies the element at index 3.
2. Output: Element at index 3 using at(): 40, then modifies the value and prints
Modified element at index 3: 45.
8. front(): Returns a reference to the first element in the vector.
1. Usage: vec.front() accesses and modifies the first element.
2. Output: First element using front(): 10, then modifies the value and prints
Modified first element: 5.
9. back(): Returns a reference to the last element in the vector.
1. Usage: vec.back() accesses and modifies the last element.
2. Output: Last element using back(): 50, then modifies the value and prints
Modified last element: 55.
10. data(): Returns a pointer to the first element in the array used internally by the vector.
You can use this pointer to access elements like a normal array.
1. Usage: vec.data() returns the pointer, and we use it to print all elements.
2. Output: Elements using data(): 5 20 35 45 55

------------------------------------------------------------------------------------
Modifiers
1. assign() – It assigns new value to the vector elements by replacing old ones
2. push_back() – It push the elements into a vector from the back
3. pop_back() – It is used to pop or remove elements from a vector from the back.
4. insert() – It inserts new elements before the element at the specified position
5. erase() – It is used to remove elements from a container from the specified position or range.
6. swap() – It is used to swap the contents of one vector with another vector of same type. Sizes
may differ.
7. clear() – It is used to remove all the elements of the vector container
8. emplace() – It extends the container by inserting new element at position
9. emplace_back() – It is used to insert a new element into the vector container, the new
element is added to the end of the vector

example
#include <iostream>
#include <vector>

int main() {
// Initialize a vector with some elements
vector<int> vec = {1, 2, 3, 4, 5};

// 1. assign() - Assigns new values to the vector


vec.assign(3, 10); // Replaces old values, new vector will have three
elements, all 10
cout << "After assign(3, 10): ";
for (int val : vec) {
cout << val << " "; // Output: 10 10 10
}
cout << endl;

// 2. push_back() - Pushes an element to the back


vec.push_back(20);
cout << "After push_back(20): ";
for (int val : vec) {
cout << val << " "; // Output: 10 10 10 20
}
cout << endl;

// 3. pop_back() - Removes the last element


vec.pop_back();
cout << "After pop_back(): ";
for (int val : vec) {
cout << val << " "; // Output: 10 10 10
}
cout << endl;

// 4. insert() - Inserts an element before the specified position


vec.insert(vec.begin() + 1, 5); // Insert 5 at index 1
cout << "After insert at index 1: ";
for (int val : vec) {
cout << val << " "; // Output: 10 5 10 10
}
cout << endl;

// 5. erase() - Removes element at the specified position


vec.erase(vec.begin() + 2); // Erase the element at index 2
cout << "After erase at index 2: ";
for (int val : vec) {
cout << val << " "; // Output: 10 5 10
}
cout << endl;

// 6. swap() - Swaps the contents of two vectors


vector<int> otherVec = {100, 200};
vec.swap(otherVec);
cout << "After swap with otherVec: ";
for (int val : vec) {
cout << val << " "; // Output: 100 200
}
cout << endl;
cout << "Contents of otherVec: ";
for (int val : otherVec) {
cout << val << " "; // Output: 10 5 10
}
cout << endl;

// 7. clear() - Removes all elements from the vector


vec.clear();
cout << "After clear(), size of vec: " << vec.size() << endl; // Output: 0

// 8. emplace() - Inserts an element at a specified position


vec.emplace(vec.begin(), 50); // Insert 50 at the beginning
cout << "After emplace at beginning: ";
for (int val : vec) {
cout << val << " "; // Output: 50
}
cout << endl;

// 9. emplace_back() - Inserts an element at the end


vec.emplace_back(60); // Insert 60 at the end
cout << "After emplace_back(60): ";
for (int val : vec) {
cout << val << " "; // Output: 50 60
}
cout << endl;

return 0;
}

Explanation of Each Method

1. assign(): Replaces the contents of the vector with n copies of a given value.
o Usage: vec.assign(3, 10); creates a vector with three elements, all set to 10.
o Output: 10 10 10
2. push_back(): Adds an element to the end of the vector.
o Usage: vec.push_back(20); adds 20 to the end.
o Output: 10 10 10 20
3. pop_back(): Removes the last element from the vector.
o Usage: vec.pop_back(); removes the last element.
o Output: 10 10 10
4. insert(): Inserts an element before the specified position.
o Usage: vec.insert(vec.begin() + 1, 5); inserts 5 at index 1.
o Output: 10 5 10 10
5. erase(): Removes the element at the specified position.
o Usage: vec.erase(vec.begin() + 2); erases the element at index 2.
o Output: 10 5 10
6. swap(): Swaps the contents of two vectors.
o Usage: vec.swap(otherVec); swaps vec with otherVec.
o Output: vec becomes 100 200, and otherVec becomes 10 5 10.
7. clear(): Removes all elements from the vector, reducing its size to zero.
o Usage: vec.clear(); clears the vector.
o Output: size of vec: 0
8. emplace(): Inserts a new element at a specified position, constructed in place.
o Usage: vec.emplace(vec.begin(), 50); inserts 50 at the beginning.
o Output: 50
9. emplace_back(): Inserts a new element at the end of the vector, constructed in place.
o Usage: vec.emplace_back(60); inserts 60 at the end.
o Output: 50 60

These examples show how to use each function to manipulate and manage a vector in C++.

Example 1: Basic Vector Operations

This example shows simple operations: adding elements, accessing them, and printing.

#include <iostream>
#include <vector>

int main() {
vector<int> vec; // Creates an empty vector

// Adding elements using push_back


vec.push_back(10);
vec.push_back(20);
vec.push_back(30);

// Access and print elements


cout << "Elements in vec: ";
for (int i = 0; i < vec.size(); i++) {
cout << vec[i] << " "; // Output: 10 20 30
}
cout << endl;

return 0;
}

Example 2: Using a Vector with Loops

Using a vector to store a series of numbers and print them using a for-each loop.

#include <iostream>
#include <vector>
int main() {
vector<int> numbers = {1, 2, 3, 4, 5}; // Initialize with values

// Using a for-each loop to print the elements


cout << "Numbers: ";
for (int num : numbers) {
cout << num << " "; // Output: 1 2 3 4 5
}
cout << endl;

return 0;
}

Example 3: Resizing and Filling a Vector

Using resize() to change the size of a vector and filling it with values.

#include <iostream>
#include <vector>

int main() {
vector<int> vec(5, 0); // Creates a vector with 5 elements, all
initialized to 0

// Resize the vector to have 8 elements, with new elements initialized to


100
vec.resize(8, 100);

// Print the elements


cout << "Elements in vec: ";
for (int val : vec) {
cout << val << " "; // Output: 0 0 0 0 0 100 100 100
}
cout << endl;

return 0;
}

Example 4: Removing Elements from a Vector

Demonstrates removing elements using pop_back() and erase().

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {10, 20, 30, 40, 50};

// Remove the last element using pop_back()


vec.pop_back(); // Removes 50
// Remove the second element using erase()
vec.erase(vec.begin() + 1); // Removes 20

// Print the elements


cout << "Elements after removal: ";
for (int val : vec) {
cout << val << " "; // Output: 10 30 40
}
cout << endl;

return 0;
}

Example 5: Vector of Strings

Using a vector to store strings and perform some operations.

#include <iostream>
#include <vector>

int main() {
vector<string> words; // Create a vector of strings

// Add some words


words.push_back("Hello");
words.push_back("World");
words.push_back("C++");

// Modify an element
words[1] = "Vector";

// Print the words


cout << "Words: ";
for (const string& word : words) {
cout << word << " "; // Output: Hello Vector C++
}
cout << endl;

return 0;
}

Summary of Examples

1. Basic Vector Operations: Demonstrates adding and printing elements.


2. Using a Vector with Loops: Uses a for-each loop to print vector elements.
3. Resizing and Filling a Vector: Shows how to use resize() and fill a vector.
4. Removing Elements from a Vector: Demonstrates pop_back() and erase().
5. Vector of Strings: Shows how to use a vector with strings and modify elements.
User input

Example 1: Taking Input to Fill a Vector

Prompting the user to enter numbers to fill a vector and then printing the vector.

#include <iostream>
#include <vector>

int main() {
vector<int> numbers;
int n, input;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter " << n << " numbers: ";


for (int i = 0; i < n; ++i) {
cin >> input;
numbers.push_back(input);
}

cout << "You entered: ";


for (int num : numbers) {
cout << num << " "; // Output: user-inputted numbers
}
cout << endl;

return 0;
}

Example 2: Calculating the Sum of Elements

Taking user input to fill a vector and calculating the sum of all elements.

#include <iostream>
#include <vector>

int main() {
vector<int> numbers;
int n, input, sum = 0;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter " << n << " numbers: ";


for (int i = 0; i < n; ++i) {
cin >> input;
numbers.push_back(input);
sum += input;
}

cout << "Sum of elements: " << sum << endl; // Output: sum of numbers
return 0;
}

Example 3: Finding the Largest Element

Taking input from the user and finding the largest number in the vector.

#include <iostream>
#include <vector>

int main() {
vector<int> numbers;
int n, input;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter " << n << " numbers: ";


for (int i = 0; i < n; ++i) {
cin >> input;
numbers.push_back(input);
}

int largest = numbers[0];


for (int num : numbers) {
if (num > largest) {
largest = num;
}
}

cout << "Largest element: " << largest << endl; // Output: largest number

return 0;
}

Example 4: Counting Even and Odd Numbers

Taking user input and counting how many numbers are even and how many are odd.

#include <iostream>
#include <vector>

int main() {
vector<int> numbers;
int n, input, evenCount = 0, oddCount = 0;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter " << n << " numbers: ";


for (int i = 0; i < n; ++i) {
cin >> input;
numbers.push_back(input);
}

for (int num : numbers) {


if (num % 2 == 0) {
evenCount++;
} else {
oddCount++;
}
}

cout << "Even numbers: " << evenCount << endl;


cout << "Odd numbers: " << oddCount << endl;

return 0;
}

Example 5: Reversing a Vector

Taking user input and reversing the vector elements.

#include <iostream>
#include <vector>

int main() {
vector<int> numbers;
int n, input;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter " << n << " numbers: ";


for (int i = 0; i < n; ++i) {
cin >> input;
numbers.push_back(input);
}

// Reverse the vector


cout << "Reversed vector: ";
for (int i = numbers.size() - 1; i >= 0; --i) {
cout << numbers[i] << " "; // Output: elements in reverse order
}
cout << endl;

return 0;
}

Summary of Examples

1. Taking Input to Fill a Vector: Collects a series of numbers from the user and prints them.
2. Calculating the Sum of Elements: Calculates and prints the sum of the user-inputted numbers.
3. Finding the Largest Element: Finds the largest number in a vector.
4. Counting Even and Odd Numbers: Counts how many numbers are even and how many are odd.
5. Reversing a Vector: Reverses and prints the elements of the vector.

C++, iterators are objects that function as pointers and are used to traverse through elements of
a container, like arrays, vector, list, or other Standard Template Library (STL) containers.
They are an integral part of the STL and provide a way to access elements in a sequential
manner, just like a pointer.

Here is a complete guide to understanding iterators in C++, including their types, common
functions, and examples.

Types of Iterators in C++


C++ offers several types of iterators, each serving different purposes:

1. Input Iterator:
o Can only be used to read elements in a forward direction.
o Suitable for single-pass input operations (e.g., reading from an input stream).

2. Output Iterator:
o Can only be used to write elements in a forward direction.
o Suitable for single-pass output operations (e.g., writing to an output stream).

3. Forward Iterator:
o Can be used to read or write elements in a forward direction.
o Supports multiple passes over the data.

4. Bidirectional Iterator:
o Can be used to read or write elements in both forward and backward directions.
o Examples include list and set.

5. Random Access Iterator:


o Can be used to read or write elements in any order.
o Provides the functionality of accessing any element directly.
o Examples include vector and deque.

2. Common Functions Used with Iterators


Iterators provide several functions to make traversal and manipulation easier:

1. begin(): Returns an iterator pointing to the first element of the container.


2. end(): Returns an iterator pointing to the past-the-end element of the container.
3. rbegin(): Returns a reverse iterator pointing to the last element of the container.
4. rend(): Returns a reverse iterator pointing to the element before the first element.
5. cbegin(): Returns a constant iterator pointing to the first element.
6. cend(): Returns a constant iterator pointing to the past-the-end element.
7. crbegin(): Returns a constant reverse iterator pointing to the last element.
8. crend(): Returns a constant reverse iterator pointing to the element before the first element.

3. Basic Example of Using Iterators with a Vector


Here is a simple example demonstrating how to use iterators with a vector:

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {10, 20, 30, 40, 50};

// Using an iterator to traverse the vector


vector<int>::iterator it;
cout << "Elements in the vector: ";
for (it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " "; // Dereferencing the iterator to get the value
}
cout << endl;

return 0;
}

Explanation:

 vector<int>::iterator: Declares an iterator for a vector of integers.


 vec.begin(): Points to the first element.
 vec.end(): Points to the element past the last element.
 *it: Dereferences the iterator to access the value.

4. Using auto with Iterators


C++11 introduced the auto keyword, which can simplify the declaration of iterators:

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {1, 2, 3, 4, 5};

cout << "Using auto keyword: ";


for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " ";
}
cout << endl;

return 0;
}

Explanation:

 auto automatically deduces the type of the iterator, making the code cleaner.

5. Using Reverse Iterators


Reverse iterators are used to traverse the container in reverse order.

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {10, 20, 30, 40, 50};

// Using reverse iterators


cout << "Elements in reverse order: ";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
cout << *rit << " ";
}
cout << endl;

return 0;
}

Explanation:

 vec.rbegin(): Points to the last element of the vector.


 vec.rend(): Points to the element before the first element.
 This allows you to iterate over the container in reverse.

6. Const Iterators
Const iterators are used when you want to make sure that the elements of the container are not
modified.

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {1, 2, 3, 4, 5};

// Using a const iterator


cout << "Using const_iterator: ";
for (vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); +
+it) {
cout << *it << " ";
// *it = 10; // Error: cannot modify the value
}
cout << endl;

return 0;
}

Explanation:

 vector<int>::const_iterator: Declares a constant iterator.


 vec.cbegin(): Returns a constant iterator to the beginning of the vector.
 vec.cend(): Returns a constant iterator to the end of the vector.
 You cannot modify the elements using a constant iterator.

7. Iterator Arithmetic (Only for Random Access Iterators)


Random access iterators support arithmetic operations like addition and subtraction.

#include <iostream>
#include <vector>

int main() {
vector<int> vec = {10, 20, 30, 40, 50};

// Demonstrating iterator arithmetic


vector<int>::iterator it = vec.begin();
it += 2; // Move the iterator forward by 2 positions

cout << "Element at position 2: " << *it << endl; // Output: 30

return 0;
}

Explanation:
 it += 2: Moves the iterator forward by two elements.
 This feature is only available for random access iterators, like those used with vector and
deque.

Summary
 Iterators in C++ are essential tools for accessing and manipulating elements in containers.
 They come in different types: input, output, forward, bidirectional, and random access.
 You can use iterator functions like begin(), end(), rbegin(), rend(), and cbegin() to
work with iterators.
 The auto keyword and reverse/const iterators make it easier and more efficient to traverse and
manipulate containers.

Example with iterators

C++ that demonstrate how to use vectors for various tasks, including taking input, performing
calculations, and using iterators.

1. Taking Input to Fill a Vector

This program collects a series of numbers from the user and stores them in a vector, then prints
the elements.

#include <iostream>
#include <vector>

int main() {
vector<int> vec;
int n, num;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter the elements:\n";


for (int i = 0; i < n; ++i) {
cin >> num;
vec.push_back(num); // Add each number to the vector
}

cout << "The elements in the vector are:\n";


for (auto it = vec.begin(); it != vec.end(); ++it) {
cout << *it << " "; // Print each element
}
cout << endl;

return 0;
}

2. Calculating the Sum of Elements

This program calculates and prints the sum of the numbers in the vector.

#include <iostream>
#include <vector>

int main() {
vector<int> vec;
int n, num, sum = 0;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter the elements:\n";


for (int i = 0; i < n; ++i) {
cin >> num;
vec.push_back(num); // Add each number to the vector
}

// Calculate sum using iterator


for (auto it = vec.begin(); it != vec.end(); ++it) {
sum += *it; // Add each element to sum
}

cout << "The sum of the elements is: " << sum << endl;

return 0;
}

3. Finding the Largest Element

This program finds and prints the largest element in the vector.

#include <iostream>
#include <vector>
#include <algorithm> // For max_element()

int main() {
vector<int> vec;
int n, num;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter the elements:\n";


for (int i = 0; i < n; ++i) {
cin >> num;
vec.push_back(num); // Add each number to the vector
}

// Using max_element to find the largest element


auto max_it = max_element(vec.begin(), vec.end());

cout << "The largest element is: " << *max_it << endl;

return 0;
}

4. Counting Even and Odd Numbers

This program counts how many even and odd numbers are in the vector.

#include <iostream>
#include <vector>

int main() {
vector<int> vec;
int n, num, even_count = 0, odd_count = 0;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter the elements:\n";


for (int i = 0; i < n; ++i) {
cin >> num;
vec.push_back(num); // Add each number to the vector
}

// Count even and odd numbers


for (auto it = vec.begin(); it != vec.end(); ++it) {
if (*it % 2 == 0) {
even_count++; // Increment even count
} else {
odd_count++; // Increment odd count
}
}

cout << "Even numbers: " << even_count << endl;


cout << "Odd numbers: " << odd_count << endl;

return 0;
}

5. Reversing a Vector

This program reverses the elements of the vector using reverse iterators and prints them.

#include <iostream>
#include <vector>

int main() {
vector<int> vec;
int n, num;

cout << "Enter the number of elements: ";


cin >> n;

cout << "Enter the elements:\n";


for (int i = 0; i < n; ++i) {
cin >> num;
vec.push_back(num); // Add each number to the vector
}

// Reverse traversal using reverse iterators


cout << "The elements in reverse order are:\n";
for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
cout << *rit << " "; // Dereference reverse iterator to print element
}
cout << endl;

return 0;
}

Explanation:

 Taking Input: Each program collects numbers from the user and stores them in a vector.
 Sum of Elements: A simple loop with iterators calculates the sum of elements.
 Largest Element: Uses the max_element() function to find the largest element.
 Even/Odd Count: The program iterates through the vector and uses modulo operation (% 2) to
count even and odd numbers.
 Reversing: A reverse iterator (rbegin(), rend()) is used to traverse the vector from the end
to the beginning.

Example with string

iterators with strings in C++, along with detailed explanations for each:

1. Traversing a String with Iterators

This example demonstrates how to use iterators to traverse through the characters of a string
and print each character.

Example: Traversing a String


#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";

// Using an iterator to traverse the string


for (string::iterator it = str.begin(); it != str.end(); ++it) {
cout << *it << " "; // Dereference the iterator to access the
character
}
cout << endl;
return 0;
}

Explanation:

 str.begin() returns an iterator pointing to the first character of the string.


 str.end() returns an iterator pointing one past the last character (the theoretical end).
 The for loop increments the iterator and prints each character of the string by dereferencing
the iterator with *it.

Output:

H e l l o , W o r l d !

2. Modifying a String Using Iterators

This example demonstrates how to modify the characters of a string using iterators. It changes all
lowercase letters to uppercase.

Example: Modifying String Characters


#include <iostream>
#include <string>
#include <cctype> // For toupper()

int main() {
string str = "hello, world!";

// Using an iterator to modify each character


for (string::iterator it = str.begin(); it != str.end(); ++it) {
*it = toupper(*it); // Convert each character to uppercase
}

cout << "Modified string: " << str << endl;

return 0;
}

Explanation:

 The for loop iterates through each character of the string.


 The iterator it points to each character, and *it is used to access and modify the character.
 The toupper(*it) function is used to convert each character to uppercase.

Output:

Modified string: HELLO, WORLD!


3. Using Reverse Iterators to Traverse a String in Reverse Order

This example demonstrates how to use reverse iterators (rbegin() and rend()) to traverse a
string in reverse order and print each character.

Example: Traversing String in Reverse


#include <iostream>
#include <string>

int main() {
string str = "Hello, World!";

// Using reverse iterators to traverse the string in reverse order


for (string::reverse_iterator rit = str.rbegin(); rit != str.rend(); +
+rit) {
cout << *rit << " "; // Dereference the reverse iterator
}
cout << endl;

return 0;
}

Explanation:

 str.rbegin() returns a reverse iterator pointing to the last character of the string.
 str.rend() returns a reverse iterator pointing one before the first character (the theoretical
reverse end).
 The for loop uses rit to iterate backward through the string, and *rit prints each character
in reverse order.

Output:

! d l r o W , o l l e H

Summary of Key Concepts:

1. Traversing with Iterators: You can use regular iterators (begin(), end()) to traverse a string
character by character.
2. Modifying Elements: You can modify characters of a string using iterators by dereferencing
them and assigning new values.
3. Reverse Traversal: Reverse iterators (rbegin(), rend()) allow you to traverse a string from
the last character to the first.

Iterator vs Normal travesing


In C++, iterators and normal traversing (typically using indices) are two different approaches
to accessing and iterating over elements in containers like vector, string, or array. Here’s a
detailed comparison between iterator-based traversal and normal traversal using indices:

1. Syntax and Style

 Iterator-based Traversal:
o Iterators are objects that point to elements in a container.
o You use begin() and end() (or rbegin() and rend() for reverse iteration) to define
the range of traversal.
o Iterators are more flexible and can work with different container types (e.g., vector,
list, string), supporting uniform syntax for all container types.

 Normal Traversal (Index-based):


o Indexing uses integer-based indices (e.g., i = 0, i < size()), which is specific to
containers that support random access, like vector or array.
o Indexing is more intuitive when you specifically need the position of the element.

2. Accessing Elements

 Iterator-based Traversal:
o You access elements through dereferencing the iterator (*it).
o Example:

for (vector<int>::iterator it = vec.begin(); it != vec.end(); +


+it) {
cout << *it << " "; // Dereference iterator to access element
}

 Normal Traversal (Index-based):


o You access elements using an index, e.g., vec[i].

Example:

for (int i = 0; i < vec.size(); ++i) {


cout << vec[i] << " "; // Direct access via index
}

3. Flexibility and Container Types

 Iterator-based Traversal:
o Works uniformly across all container types in C++ Standard Library (such as vector,
list, map, etc.), including those that do not support direct indexing.
o Iterators work with non-contiguous containers like list and set where random access
(indexing) is not available.
o Example: You can use iterators with containers like list which don’t support direct
indexing.
 Normal Traversal (Index-based):
o Limited to containers that support random access (like vector, array).
o Containers like list or map do not allow direct indexing.
o Example: list<int> lst; does not support lst[i].

4. Reverse Traversal

 Iterator-based Traversal:
o Iterators provide built-in support for reverse iteration using reverse iterators
(rbegin() and rend()).
o Example:

for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {


cout << *rit << " "; // Reverse traversal
}

 Normal Traversal (Index-based):


o Reverse traversal is less intuitive and requires using a decreasing index manually.

Example:

for (+1 c k 0; --i) {


cout << vec[i] << " "; // Reverse traversal with index
}

5. Safety and Error Prevention

 Iterator-based Traversal:
o Iterators automatically handle boundary conditions and are safer when iterating
through containers, reducing the risk of accessing out-of-bounds elements.
o With iterators, it’s less likely to make errors like accessing an invalid index.

 Normal Traversal (Index-based):


o Indexing requires careful boundary checking to avoid out-of-bounds access, and errors
like accessing negative indices or indices beyond the container size can occur.
o Example: vec[i] will throw an error if i is out of bounds.

6. Performance Considerations

 Iterator-based Traversal:
o Typically, iterators and index-based access have similar performance for containers like
vector (since both are random access).
o For containers like list, iterators are more efficient, as they are optimized for linked
structures and allow for constant-time traversal.

 Normal Traversal (Index-based):


o For random access containers (vector or array), indexing has constant-time
complexity (O(1)), similar to iterators.
o For containers like list, where traversal takes linear time (O(n)), index-based access is
not applicable.

7. Compatibility with Algorithms

 Iterator-based Traversal:
o Iterators are widely used with the C++ Standard Library algorithms (like for_each,
sort, find, etc.).
o Example using an algorithm with iterators:

for_each(vec.begin(), vec.end(), [](int n) { cout << n << " "; });

 Normal Traversal (Index-based):


o Index-based access is less compatible with many STL algorithms, as most algorithms
expect iterators.

8. Use with Non-Contiguous Containers

 Iterator-based Traversal:
o Works seamlessly with all types of containers, including non-contiguous ones like list,
set, map, and others.
o Example:

list<int> lst = {1, 2, 3, 4, 5};


for (auto it = lst.begin(); it != lst.end(); ++it) {
cout << *it << " "; // Works with list
}

 Normal Traversal (Index-based):


o Not applicable for containers like list because these containers do not support direct
indexing.

Summary of Differences

Feature Iterator-based Traversal Normal Traversal (Index-based)

Uses begin() and end() or


Syntax Uses indices, e.g., vec[i]
rbegin()/rend()

Container Only works with random-access


Works with all containers (e.g., list, vector)
Compatibility containers (e.g., vector, array)

Reverse Traversal Built-in support (rbegin(), rend()) Requires manual index


Feature Iterator-based Traversal Normal Traversal (Index-based)

manipulation

Risk of accessing out-of-bounds if


Safety Safer, no out-of-bounds access
not careful

Use with Less compatible with STL


Compatible with STL algorithms
Algorithms algorithms

Similar performance for random-access O(1) for random access, but not
Performance containers; more efficient for non-random applicable for non-random
containers containers

More flexible, especially for non-contiguous Simpler for containers that support
Ease of Use
containers indexing

Both iterator-based traversal and index-based traversal have their strengths and are suited to
different situations. Iterators are more flexible, safe, and compatible with a wide range of
containers, making them a powerful feature in C++. However, for simple, random-access
containers like vector, index-based traversal may be more intuitive and easier to write

You might also like