We can add and remove elements to or from a vector using the void vector<T>::push_back(T value) and void vector<T>::pop_back() functions. The syntax vector<T> is used to indicate “a vector of the type T” where T could be anything - string, int, etc... So vector<T>::push_back says something like “the push_back function for a vector of type any type ’T’” push_back(T value) takes a value of the type the vector can contain (type T) and adds it to the end of the vector. pop_back() simply removes the last element.
vector<int> values = {1, 2, 3};
values.push_back(4); // now 1,2,3,4
values.push_back(5); // now 1,2,3,4,5
values.pop_back(); // now 1,2,3,4
values.pop_back(); // now 1,2,3
values.pop_back(); // now 1,2
The end of a vector is the “normal” location to add or remove elements due to the way the data is stored. All of the elements of a vector are stored in one contiguous block of memory. So if we want to remove something from the middle, everything after the removed item needs to shift over to fill in the hole that was made. Similarly, to insert something in the middle, we first need to move all of the elements after that point over to make a place for the new element. When using a vector we do not have to worry about doing this work ourselves - it is done by the vector for us - but it does explain why there is a push_back() and not a push_front() or push_middle().
If we do want to remove an element at another location, there is an .erase(iterator) member function. It requires an iterator be passed as the parameter. Iterators are objects that store (and manipulate) a location in a collection of data. For now, all we need to know about iterators is how to make one. To make an iterator that points to index X of a vector named vectorName, you can specify vectorName.begin() + X. And if you want to point at index 0, you can just say vectorName.begin(). For example:
vector<int> values = {1, 2, 3, 4, 5};
values.erase(values.begin() + 2); // remove the element at index 2
// now values is {1, 2, 4, 5}
values.erase(values.begin()); // remove the element at index 0
// now values is {2, 4, 5}
It is possible to remove a whole range of elements by specifying a start and end location. All the items from start, up to but not including the end location, will be removed. This means that to specify removing up to and including the last element, we want to pass in the location that is AFTER the last element. In a vector with 3 items, the last element is at index 2. So we would use vectorName.begin() + 3 to specify “until the end of the vector”. Fortunately, rather than do this, we can also just say vectorName.end():
vector<int> values = {1, 2, 3, 4, 5, 6, 7, 8};
// remove all the elements from index 0 up to (but not including) index 3
values.erase(values.begin(), values.begin() + 3);
// now values is {4, 5, 6, 7, 8}
// remove all the elements from index 2 to the end
values.erase(values.begin() + 2, values.end());
// now values is {4, 5}
To clear out all the elements in a vector, we can either say to erase from the beginning to the end, or use the .clear() method of the vector:
// remove all the elements:
values.erase(values.begin(), values.end());
// or more succinctly:
values.clear();
The .insert(iterator, value) function works by the same logic to specify where you wish to insert a value. Whatever value is currently at that location and anything after it are “pushed over” one location so that the new value can be placed in the specified location. This program uses insert to add some items to a vector: