Four ways to iterate through a C++ STL vector

When I code in C++, consistently fall in the mindset in how to iterate over a collection? It is evident that depending of the type of collection (e.g. list, set, map, vector, array, and more). However, most of them follow the same structure with few changes like accessing, inserting, deleting, modifying (CRUD ?). In any case, to set a structure I selected the std::vector to iterate using four alternative ways 😎

Setup

Before starting with the alternative ways to iterate over each element of a vector, lets to set a simple std::vector. Thus, a variable vecValues is created which is defined as a vector if integers filled with 50 arbitrary numbers from -100 to +100.

This is achieved employing an engine for random numbers with a uniform distribution. In the following code is shown how is to perform that.

#include <vector>
#include <random>
#include <algorithm>
#include <iostream>

int main() {
	std::default_random_engine engine;
	const std::uniform_int_distribution<int> uniformDist(-100, +100);
	std::vector<int> vecValues;
	vecValues.resize(50);

Note that the seed is the same for each time uniformDist is called. With this, we can check the output for testing. Using a seed will generate different random numbers for each invocation. Note that this approach would be using only for development environment 🤪

std::generate(vecValues.begin(), vecValues.end(), [uniformDist, &engine]() {
	return uniformDist(engine);
	});

To fill the vector with values, the function generate which is called with a lambda function only just returning the following element of the random generator engine. Now, with a vector filled with random number, the subsequent step is checked which elements are stored on it.

via GIPHY

Iterate using indexing

Using an index is a most used/classic way to iterate over the vector in C++, which is used in normal loops. With this approach it is possible to know the index position of the elements. The for loop is used to explore from position 0 to the latter position in the vector:

for (size_t iIndex = 0; iIndex < arrValues.size(); iIndex++)
    std::cout << vecValues[iIndex] << " ";
std::cout << std::endl;

Plus, always depending of the compiler, the datatype of the index could be from the identical type of the vector; in this case a vector<int>::size_type as follows:

for (typename std::vector<int>::size_type iIndex = 0; iIndex < vecValues.size(); iIndex++)
    std::cout << vecValues[iIndex] << " ";
std::cout << std::endl;

Iterate using Iterators

The most classic C++ way to iterate over elements is using iterators. Remember that using vector::begin( ) and vector::end( ) allow accessing at pointers to the start and end of a vector respectively. Moreover, you can use vector::rbegin( ) and vector:rend( ) to get the reverse iterator pointing the last and the first element respectively.

In the following code, we use auto instead of std::vector::iterator datatype. Why? My personal reason: I only use auto for long and annoying types to write it and for iterators.

for (auto it = vecValues.begin(); it != vecValues.end(); it++)
    std::cout << *it << " "; 
std::cout << std::endl;

Iterate using std::for_each

The function for_each is one of my favorites in the STL. This allows applying a particular function to each element in a range. Explicitly, the range is from the begin( ) to end( ). The function to apply on that range is a lambda function. In next post, I will talk about lambda functions (I promise!) 🤖

To summarize, the function should be invoked as for_each(begin, end, callback), in this case, the callback is the lambda.

std::for_each(vecValues.begin(), vecValues.end(), [](const int & iValue) {
	std::cout << iValue << " ";
	});
std::cout << std::endl;

Notice the lambda function (that could be a typical function actually) only print the parameter iValue that represents an element of the vector. In fact, it is possible to replace

const int & iValue.

by

auto & iValue.

In some context, this way is know as the one-liner function to do almost anything over a collection.

Iterate using range-based for loop

Last but foremost, we can use the range-based for loops which were introduced in C++11. This serves to loop over a container in more readable manner as many other programming languages.

In my opinion, this an elegant and clean way to access element for simple tasks (as printing in this case). The code is as follow:

for (const int& iItem : vecValues)
	std::cout << iItem << " ";
std::cout << std::endl;

Similarly, we can replace the const int & for an auto & or just auto. In this case, we do not require the & because there are not modifications over the elements in the vector.

I am not using a std::vector, just a regular int []

Suppose that you are working with the classic old-fashion C array style (with the proper malloc/free) or C++ (new/delete), you might use the iterations techniques explained above. To be consistent with the C++ style, the STL provides a couple of extraordinary functions: begin and end which returning an iterator to the beginning of a given range. This function could be executed in the regular containers, however, these already perform those functions as members 😬

Next, let me create a snigle integer array with only 3 values and iterating using Iteratos:

const int arrValues[]{ uniformDist(engine), uniformDist(engine), uniformDist(engine) };
for (auto it = std::begin(arrValues); it != std::end(arrValues); it++)
	std::cout << *it << " ";
std::cout << std::endl;

At this point, we can iterate over all elements of a vector using different methods. Naturally, those could be applied in the same way to other collections (the accessing should be different is most cases).

Which one is worthier? The classic answer: up to you. Thought, range-based for loops allows more readability; for one-liners the for_each() should be your choice; if the project uses iterators? then use iterators! and so on, always depend on your setup.

I hope this would be valuable to other developers 🤖

From a geek to geeks.


Share Tweet Send
0 Comments
Loading...
You've successfully subscribed to The ecode.DEV repository
Great! Next, complete checkout for full access to The ecode.DEV repository
Welcome back! You've successfully signed in
Success! Your account is fully activated, you now have access to all content.