C++ Vectors

Vectors are a data structure provided as part of the Standard Template Library (STL) and are categorised as a sequence container, along with STL arrays, deques and lists.

Vectors, like arrays, can contain multiple values of the same type, however they are a lot more flexible than arrays, due to the ease of adding and removing values. Unlike with arrays, the number of values in a vector does not have to be specified when it is defined.

The example below creates a vector of strings called ‘names’, adds four names using the ‘push_back’ method, then, with a range based ‘for’ loop, displays the names in the console. In order to utilise vectors, the ‘vector’ header file must be included.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

for (auto name: names)
{
    cout << name << endl;
}

The output from this will be as follows.

Bob
George
Fred
Alan

Note that, like with an array, an ordinary ‘for’ loop could be used, as shown below, but a range based ‘for’ loop is simpler.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

for (unsigned int i = 0; i < names.size(); ++i)
{
    cout << names.at(i) << endl;
}

Here, the ‘size’ method of the vector is used to help determine the number of iterations of the loop, whilst the ‘at’ method, in conjunction with the loop counter variable, ‘i’, provides access to the individual vector values. As with arrays, each element in a vector has an index value, which starts at zero. An unsigned integer is again used for the loop counter.

The ‘at’ method is one of two ways to access individual values stored inside a vector. Vectors can also be accessed using array like syntax.

cout << names.at(0) << endl;
cout << names[0] << endl;

Both of the above will display the first element contained within the vector. Similarly, a value within a vector can be updated using vector syntax, with the ‘at’ method or, array like syntax.

names.at(1) = "Janice";
names[1] = "Janice";

Here, the second element in the vector is updated to ‘Janice’ in both cases.

An ordinary ‘for’ loop can also be used in conjunction with an iterator to loop through a vector, in a similar way as with STL arrays.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

// Iterator declaration.
vector<string>::iterator i;

// Loop through the vector with the iterator.
for (i = names.begin(); i != names.end(); ++i)
{
    cout << *i << endl;
}

Here, the ‘begin’ and ‘end’ methods are used to denote the start and end of the vector. The ‘end’ method does not point to the last item in the vector, but instead points to just after the last item, which is why ‘not equal to’ is used in the loop, rather than ‘less than or equal to’. Notice that when displaying the values in the vector, within the loop, an asterisk precedes the iterator, in order to refer to the actual values within the vector. This example will display the names on a separate line as before.

It isn’t absolutely necessary to declare the iterator prior to the loop, it can be done as part of the loop.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

// Loop through the vector with the iterator.
for (vector<string>::iterator i = names.begin(); i != names.end(); ++i)
{
    cout << *i << endl;
}

To further simplify this, the ‘auto’ keyword can be used, which forces the compiler to determine that an iterator is to be used.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

// Loop through the vector with the iterator.
for (auto i = names.begin(); i != names.end(); ++i)
{
    cout << *i << endl;
}

To ensure that the values within the vector are not altered within the loop, the ‘begin’ and ‘end’ methods can be replaced by ‘cbegin’ and ‘cend’.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

// Loop through the vector with the iterator.
for (auto i = names.cbegin(); i != names.cend(); ++i)
{
    cout << *i << endl;
}

If required, it is also possible to loop through the vector in reverse by replacing the ‘begin’ and ‘end’ methods with ‘rbegin’ and ‘rend’.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

// Loop through the vector with the iterator.
for (auto i = names.rbegin(); i != names.rend(); ++i)
{
    cout << *i << endl;
}

In order to remove a value from a vector, there are a couple of different ways, depending on which value needs to be deleted. If the last value in the vector needs to be removed, then the ‘pop_back’ method can be used.

names.pop_back();

If a specific value needs to be removed and the index is known, the ‘erase’ method can be utilised.

names.erase(names.begin()+2);

Here, the value with an index of two, in this case, ‘Fred’, will be removed.

Some other useful methods to note are the ‘front’ method, that returns the first item it the vector and the ‘back’ method, which returns the last item.

vector<string> names;
names.push_back("Bob");
names.push_back("George");
names.push_back("Fred");
names.push_back("Alan");

cout << names.front() << endl;
cout << names.back() << endl;

This will display the following in the console.

Bob
Alan

It is also possible to sort the values within a vector using the ‘sort’ function. In the case of the ‘names’ vector above, this will place the values in alphabetic order. The ‘algorithm’ header file must be included for the ‘sort’ function to be utilised.

sort(begin(names), end(names));