Vector Part 1
Sequence containers in C++ are a category of containers within the Standard Template Library (STL) that store elements in a sequential order. They provide dynamic storage allocation and support various operations for accessing, inserting, and removing elements. Sequence containers are primarily categorized based on how they organize and manage their elements. Here’s an explanation of the commonly used sequence containers:
Arrays
Arrays are considered as a kind of sequence container in C++. However, they are typically categorized separately from other sequence containers like vectors, lists, and deques because of their fixed size nature and the absence of dynamic resizing capabilities.
Vector
Characteristics:
- Fast insert/ remove at the end
- Slow insert/ remove at the beginning or in the middle
- Slow search
Example 1:
#include <iostream> #include <vector> using namespace std; int main() { vector<int>v(4); v[0] = 10; v.push_back(50); return 0; }
This code snippet attempts to create a vector of integers with an initial size of 4 elements, assigns a value to the first element, and then tries to add an additional element using the push_back function. However, there’s a potential issue with the usage of push_back after specifying the initial size.
Let’s analyze the code and discuss the implications:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v(4); // Creates a vector with 4 elements, all initialized to 0 v[0] = 10; // Assigns a value of 10 to the first element of the vector v.push_back(50); // Attempts to add an additional element with the value 50 // This line may lead to undefined behavior because it's // appending an element beyond the originally specified size return 0; }
Explanation:
- The line vector<int> v(4); creates a vector v with an initial size of 4 elements, all initialized to the default value of integers (which is 0).
- Then, v[0] = 10; assigns a value of 10 to the first element of the vector.
- However, the subsequent line v.push_back(50); attempts to add an additional element to the vector using push_back. Since the vector was initially sized to contain only 4 elements, appending an element beyond this size may cause undefined behavior. The push_back operation might trigger a reallocation of the vector’s underlying storage, which could lead to memory corruption or other unexpected behavior.
Example 2:
#include <iostream> #include <vector> using namespace std; int main() { vector<int>v = {1, 2, 3, 4}; // Initialize vector v with values 1, 2, 3, 4 vector<int>v2(v); // Initialize vector v2 as a copy of v cout << v2[0]; // Output the first element of v2 return 0; }
This code snippet initializes a vector v with four integers {1, 2, 3, 4}, and then attempts to initialize another vector v2 as a copy of v.
The output will be 1, as it prints the first element of v2, which is a copy of v. Therefore, it will print the first element of v, which is 1.
Example 3:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v(5, 100); // Initialize vector v with 5 elements, each set to the value 100 vector<int> v2(6, 200); // Initialize vector v2 with 6 elements, each set to the value 200 cout << v2[0] << endl; // Output the first element of v2 return 0; }
In this code:
- vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100. This constructor initializes v with 5 elements, each having the value 100.
- vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200. This constructor initializes v2 with 6 elements, each having the value 200.
- cout << v2[0] << endl; prints the first element of v2, which is 200, followed by a newline character.
So, the output of this code will be:
200
Example 4:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v(5, 100); // Initialize vector v with 5 elements, each set to the value 100 vector<int> v2(6, 200); // Initialize vector v2 with 6 elements, each set to the value 200 v.swap(v2); // Swap the contents of v and v2 cout << v2[0] << endl; // Output the first element of v2 return 0; }
In this code:
- vector<int> v(5, 100); creates a vector v with 5 elements, each initialized to the value 100.
- vector<int> v2(6, 200); creates a vector v2 with 6 elements, each initialized to the value 200.
- v.swap(v2); exchanges the contents of v and v2, effectively swapping the elements and sizes of the two vectors.
- cout << v2[0] << endl; attempts to print the first element of v2.
However, after the swap operation, v2 now contains the elements originally in v, and v contains the elements originally in v2. Therefore, attempting to access v2[0] will actually print the first element of the vector that was initially v.
So, the output of this code will be:
100
Example 5:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v; // Create an empty vector v.push_back(10); // Add 10 to the end of the vector v.push_back(20); // Add 20 to the end of the vector v.push_back(30); // Add 30 to the end of the vector cout << v.front() << endl; // Output the first element of the vector cout << v.back() << endl; // Output the last element of the vector cout << v.at(0) << endl; // Output the element at index 0 of the vector return 0; }
Here’s what each line of the code does:
- vector<int> v;: Declares an empty vector of integers.
- v.push_back(10);: Appends the value 10 to the end of the vector v.
- v.push_back(20);: Appends the value 20 to the end of the vector v.
- v.push_back(30);: Appends the value 30 to the end of the vector v.
- cout << v.front() << endl;: Outputs the first element of the vector v using the front() member function. In this case, it prints 10.
- cout << v.back() << endl;: Outputs the last element of the vector v using the back() member function. In this case, it prints 30.
- cout << v.at(0) << endl;: Outputs the element at index 0 of the vector v using the at() member function. In this case, it prints 10.
So, the output of this code will be:
10 30 10
Example 6:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> v(100); // Create a vector with 100 elements, all initialized to 0 v.push_back(5); // Append the value 5 to the end of the vector cout << "Size = " << v.size() << endl; // Output the current size of the vector cout << "Capacity = " << v.capacity() << endl; // Output the current capacity of the vector return 0; }
Here’s what each line does:
- vector<int> v(100);: Creates a vector v with an initial size of 100 elements, all initialized to the default value of int, which is 0.
- v.push_back(5);: Appends the value 5 to the end of the vector. Since the vector was initialized with a size of 100, but only one element was added, the vector will resize itself as needed to accommodate the new element.
- cout << “Size = ” << v.size() << endl;: Outputs the current size of the vector using the size() member function. In this case, it prints 101, as there are now 101 elements in the vector.
- cout << “Capacity = ” << v.capacity() << endl;: Outputs the current capacity of the vector using the capacity() member function. The capacity represents the maximum number of elements that the vector can hold without reallocating memory. In this case, it depends on the implementation, but it’s likely to be greater than or equal to 101, as the vector may allocate additional memory to avoid frequent reallocations when more elements are added.
Example 7:
#include <iostream> #include <vector> using namespace std; int main() { vector<int>v = {1, 2, 3, 4, 5}; for (size_t i = 0; i < v.size(); i++) { cout << v[i] << " "; } return 0; }
Here’s what each line of the code does:
- vector<int> v = {1, 2, 3, 4, 5};: Initializes a vector v with five elements, each containing the values 1, 2, 3, 4, and 5, respectively.
- for (size_t i = 0; i < v.size(); i++) { … }: This is a traditional for loop that iterates over each element of the vector. It starts with an index i of 0 and continues until i is less than the size of the vector (v.size()).
- size_t is an unsigned integer type used for representing sizes of objects. It’s commonly used for indices and sizes of containers like vectors.
- cout << v[i] << ” “;: Within the loop, it prints the value of the element at index i of the vector, followed by a space.
So, the output of this code will be:
1 2 3 4 5
It prints each element of the vector v separated by a space.
Deque
Characteristics:
- Fast insert/ remove at the beginning and at the end
- Slow insert/ remove at the middle
- Slow research
List
Characteristics:
- Fast insertion and removal of elements from anywhere in the container
- Fast random access is not supported. It’s slow at accessing items from the middle
- Slow search
- Doubly-linked list
Forward List
Characteristics:
- First insertion and removal of elements from anywhere in the container
- Fast random access isn’t supported
- Singly-linked list