When it comes to the fundamentals of computer programming, arrays will almost always make an appearance. Being able to store a collection of values could be beneficial to a near endless amount of use-cases.
To continue the back to the basics programming series, in this tutorial we’ll explore standard arrays as well vectors which are a much more powerful alternative when it comes to C++.
If you’re just getting started with C++ and aren’t sure how to configure your development environment, check out this previous tutorial I wrote titled, Configure Visual Studio Code for C++ Development.
We’re going to take a look at a few array examples to help us understand how to use them in our applications.
Let’s say that we want to store a few related integer values and print them out. We could write something like this:
int values[4];
values[0] = 2;
values[1] = 4;
values[2] = 6;
values[3] = 8;
cout << values[0] << endl;
cout << values[1] << endl;
cout << values[2] << endl;
cout << values[3] << endl;
The above example creates an array of integers with a length of four. This means four integer values can be added to it, starting from the zero index. Even though the length is four, an index of four might cause an out of bounds exception. Remember, arrays in C++ and in most languages, start at zero.
It isn’t always necessary to explicitly define the array size or manually enter the values for each index one at at a time. Instead, something like this can be accomplished:
int values[] = { 2, 4, 6, 8 };
cout << values[0] << endl;
cout << values[1] << endl;
cout << values[2] << endl;
cout << values[3] << endl;
Notice that the above code accomplishes the same outcome as the first example.
Arrays in C++ are not dynamic, as in once they’ve been sized and created, the size cannot be easily changed. This means if our array has a size of four, we can’t just change it to something larger later.
When using standard arrays, the best way to resize an array would be to copy the contents of the original array into a much larger new array. We can accomplish this through the following example:
int src[] = { 2, 4, 6, 8 };
int dest[10];
copy(src, src + 10, dest);
int s_size = sizeof(src) / sizeof(*src);
int d_size = sizeof(dest) / sizeof(*dest);
cout << s_size << " / " << d_size << endl;
for(int i = 0; i < d_size; i++) {
cout << dest[i] << endl;
}
While the copy
function is the important function to us, we’re introducing a few new things as well. We’re introducing the sizeof
function which will get us the size of the array, not necessarily the length.
So let’s take a step back with the copy
function. We define our source array which has a length of four. To resize the array we are creating a new array with a length of ten. Using the copy
function we can copy the contents of the source array into the new array.
When calculating the size using the sizeof
function, we are given the actual size. For example each element in an integer array can have a maximum size of four bytes. This means if we have a length of four, our size will actually be sixteen. We need to do some division to get a length.
As of now, the way we’ve been creating our arrays, they are automatically deallocated from memory when the encapsulating function terminates. There are other methods to create arrays in C++ where the behavior is different.
Take the following example:
int *values = new int[4];
values[0] = 2;
values[1] = 4;
values[2] = 6;
values[3] = 8;
delete[] values;
for(int i = 0; i < 4; i++) {
cout << values[i] << endl;
}
When using the new
operator the memory will be allocated until the program terminates or until it is manually deallocated with the delete[]
operator. Just because it has been deallocated doesn’t mean the application has immediately reclaimed the memory. The data may or may not be present when you try to access it again.
This brings us to vectors which are a little more pleasant to work with than standard arrays, at least in C++.
Vectors work in a similar fashion to arrays in C++, but they handle all the memory related tasks for you and they offer quite a few helpful functions that weren’t available with regular arrays.
Take the following example:
vector<int> values;
values.push_back(2);
values.push_back(6);
values.push_back(8);
for(int i = 0; i < values.size(); i++) {
cout << i << ": " << values[i] << endl;
}
The above vector example tries to replicate what we had seen with arrays. We can add as many integer values as we want to it by using the push_back
method. We can obtain the length of the vector by calling the size
function which in this example we’re using as part of our loop.
Let’s take a look at some of those helpful vector functions:
vector<int> values;
values.push_back(44);
if(values.empty() == false) {
values.clear();
}
values.push_back(2);
values.push_back(4);
for(int i = 0; i < values.size(); i++) {
cout << i << ": " << values.at(i) << endl;
}
We can check to see if a vector has any values in it through the empty
function and we can remove all values from the vector through the clear
function.
In the previous example we accessed values by directly referencing the index. For example we had done values[i]
, but we can also do values.at(i)
if we wanted to.
While we could use a numeric loop on a vector, we can also use an iterator. In fact, to insert or remove values from a vector, we need to use an iterator.
vector<int> values;
values.push_back(2);
values.push_back(4);
values.push_back(6);
for(vector<int>::iterator it = values.begin(); it != values.end(); it++) {
if(*it == 4) {
values.insert(it + 1, 7);
break;
}
}
for(int i = 0; i < values.size(); i++) {
cout << values[i] << endl;
}
In the above example we are adding values to a vector, then we loop through the values using an iterator. If the current vector value is equal to four, then we insert a seven after the four.
The final example we’ll see has to do with manually resizing a vector.
Pushing values to the end of the vector will automatically resize it, but we can also manually resize it. Say for example you want to access a particular element at a position that hasn’t yet been allocated. We can do the following:
vector<int> values;
values.push_back(2);
values.push_back(4);
values.push_back(6);
values.resize(10);
values[5] = 10;
for(vector<int>::iterator it = values.begin(); it != values.end(); it++) {
cout << *it << endl;
}
With the resize
function we can increase the vector size to something specific and then proceed to access specific elements by their index.
You just saw a back to the basics example around arrays and vectors in C++. While vectors are specific to C++, the concept of arrays is a fundamental for every programming language and is essential when starting a computer science course and your career.
There were several examples of loops in this particular tutorial. If you’d like to learn more about loops in C++, I encourage you to check out my previous tutorial titled, Getting Familiar with Loops in C++.