C++ Arrays

In C++, an array is a special type of variable that contains multiple values of the same type. The following integer variable, ‘age’, has been defined and initialised with the value 30.

int age = 30;

If multiple ages need to be stored, instead of having a different variable for each, an array could be used.

int age[4];
age[0] = 30;
age[1] = 24;
age[2] = 53;
age[3] = 19;

The first line in the above example declares an array called ‘age’, which holds four integer elements. Each element in an array has an index number, which is used in lines two to five above to populate the four elements. Notice that the first index number is a zero and not a one.

The above example can be shortened by declaring and initialising the array in one statement.

int age[4] = {30, 24, 53, 19};

If an array is declared and initialised in this way, then the size in the square brackets can be omitted. In this case the size of the array is determined by the number of values that it is being initialised with.

int age[] = {30, 24, 53, 19};

It should be noted that if the array size is specified within the square brackets and only some of the elements are initialised, then the remainder are automatically initialised to zero.

As well as being able to use the index number to populate a particular element in an array, it can also be used to extract the value of an element in an array, in order to carry out a particular task, or simply just to display it.

cout << age[2] << endl;

Here, the element with an index number of two would be displayed, in this case 53.

In order to display all of the elements in an array a ‘for’ loop can be used.

int age[] = {30, 24, 53, 19};

for (unsigned int i = 0; i < sizeof(age)/sizeof(age[0]); ++i)
{
    cout << age[i] << endl;
}

The above example uses the ‘sizeof’ function to help determine the length, or size of the array. The ‘sizeof’ function returns the number of bytes of memory that the array takes up, which is why it needs to be divided by the size, or number of bytes, for one of the elements, in order to determine the number of elements that there are. The result of this calculation dictates the number of iterations through the loop. One further thing to note is that an ‘unsigned int’ is used as the loop counter. This is an integer that cannot have a value below zero. The resulting output will list all the elements of the array on a separate line.

30
24
53
19

To simplify the task of processing all the values in an array, a variation of a ‘for’ loop can be used, which is known as a range based ‘for’ loop or ‘foreach’ loop. This allows the above example to be re-written as follows.

int age[] = {30, 24, 53, 19};

for (int item: age)
{
    cout << item << endl;
}

Here, the variable ‘item’ is set to a different value from the array with each iteration through the loop. This variable is then used in the body of the loop to display its value. The type of variable used in the loop should be the same as the array, in this case, ‘int’. The resulting output is exactly the same as before.

To further simplify the above example, the variable type, ‘int’, for the loop variable, ‘item’, can be replaced with the keyword ‘auto’. When this is used the compiler determines the variable type based on the array being iterated over.

int age[] = {30, 24, 53, 19};

for (auto item: age)
{
    cout << item << endl;
}

Multidimensional Arrays

Multidimensional arrays are useful where you have more than one piece of information, so, to continue with the above example, if it were necessary to store the ages of different groups of people, with four people in each group.

int age[][4] = {
    {30, 24, 53, 19},
    {69, 48, 17, 50},
    {21, 62, 78, 44},
    {32, 41, 36, 39},
    {27, 63, 47, 22}
};

A two dimensional array, such as the one above is in effect an array of arrays. It should be noted that the size of the inner arrays must be specified, in the above case, four, but it isn’t necessary to with the outer array.

In order to process the information in a two dimensional array, nested ‘for’ loops need to be used, one to process the rows and another for the columns within each row. In the example below, the calculations to compute the number of rows and columns have been taken out of the ‘for’ loop definitions for simplicity sake, however, there is no reason why these can’t be directly inside the loop, as in the above example.

The inner loop displays the group values, separated by a space, on the same line, in the console. With each iteration through the loop, the age is added to the group total and once all the values in the group have been displayed, an average is calculated and displayed. The average is rounded to the nearest whole number using the ’round’ function. It should be noted that in order to use the ’round’ function, the ‘cmath’ header file must be included.

int age[][4] = {
    {30, 24, 53, 19},
    {69, 48, 17, 50},
    {21, 62, 78, 44},
    {32, 41, 36, 39},
    {27, 63, 47, 22}
};

// Number of rows = Total array size / size of first inner array.
int rows = sizeof(age)/sizeof(age[0]);

// Number of columns = Size of first inner array / size of first element in inner array.
int cols = sizeof(age[0])/sizeof(age[0][0]);

float groupTotal = 0.0;

// Process the rows in the outer array.
for (int i = 0; i < rows; ++i)
{
    // Process the columns in the inner array.
    for (int j = 0; j < cols; ++j)
    {
        // Add the age to the group total.
        groupTotal += age[i][j];

        // Display the age.
        cout << age[i][j] << " ";
    }
    // Calculate and display the group average age.
    cout << "   Average Group Age: " << (round(groupTotal / cols)) << endl;

    // Reset the group total.
    groupTotal = 0.0;
}

The output from this is shown below.

30 24 53 19   Average Group Age: 32
69 48 17 50   Average Group Age: 46
21 62 78 44   Average Group Age: 51
32 41 36 39   Average Group Age: 37
27 63 47 22   Average Group Age: 40

Standard Template Library Arrays

The Standard Template Library, or STL for short, provides common programming data structures and functions. These data structures, or containers, as they are also known as, include vectors, deques, lists, sets, maps, queues and stacks.

The Standard Template Library also brings with it, enhanced array functionality. In modern C++, the arrays discussed above are sometimes referred to as raw arrays and Standard Template Library arrays are actually based on these. The STL further categorises containers as sequence containers, associative containers and container adapters. An array is a type of sequence container, along with vectors, deques and lists.

In order to utilise this type of array, the ‘array’ header file needs to be included. As with raw arrays, STL arrays are fixed in size and can be declaring as follows.

array<int, 4> age = {30, 24, 53, 19};

This example is an array of four integers, with a name of ‘age’, similar to the raw array above.

As well as being able to loop through this type of array with both a ‘for’ loop and a range based ‘for’ loop, in the same way as raw arrays, it is also possible to use an iterator. An iterator works in a similar manner to a pointer, it points to the elements inside a container. An iterator can be declared in a similar way to an ordinary variable. It should be noted that it must be of the same type and size of the array being iterated over.

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

// Iterator declaration.
array<int, 4>::iterator i;

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

Here, the ‘begin’ and ‘end’ methods are used to denote the start and end of the array. The ‘end’ method does not point to the last item in the array, 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 array, within the loop, an asterisk precedes the iterator, in order to refer to the actual values within the array. This example will display the ages 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.

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

// Loop through the array with an iterator.
for (array<int, 4>::iterator i = age.begin(); i != age.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.

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

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

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

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

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

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

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

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

As well as the ‘begin’ and ‘end’ methods of an array, along with their variations, there are also some other useful methods to note. There is a ‘size’ method to determine the size of the array, a ‘front’ method to access the first item in an array and a ‘back’ method to access the last item in an array.

// Array declaration.
array<int, 4> age = {30, 24, 53, 19};

cout << age.size() << endl;
cout << age.front() << endl;
cout << age.back() << endl;

This will display the following in the console.

4
30
19