Skip to main content

8 ways to iterate a container in C++

·3 mins

You can try the below examples in C++ Shell.

1. Traditional for loop #

It is the oldest way to iterate over a container. It was part of the C language and was later included in C++ when it was created. This for loop variant uses the index to access the elements of the array.

#include <iostream>
#include <array>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    for (size_t i = 0; i < arr.size(); ++i)
    {
        std::cout << arr[i] << " ";
    }
    return 0;
}

2. While loop #

Same as the previous example, but using a while (or do while) loop and the initialization of the index variable happens outside the loop. The index is incremented inside the loop, at the end of each iteration.

#include <iostream>
#include <array>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    size_t i = 0;
    while (i < arr.size())
    {
        std::cout << arr[i] << " ";
        i++;
    }
    return 0;
}

3. Pointer arithmetic #

It is a low-level way to iterate over an array and is usually not good practice because of potential out-of-bounds errors. The pointer is incremented at the end of each iteration to move to the next element.

#include <iostream>
#include <array>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    int* ptr = &arr.front();
    int* end = &arr.back() + 1;
    while (ptr < end)
    {
        std::cout << *ptr << " ";
        ptr++;
    }
    return 0;
}

4. Goto statement #

I am giving this example just for the sake of completeness. It is not recommended to use goto statements in C++ because it can make the code hard to read and understand.

#include <iostream>
#include <array>

int main()
{
    std::array<int, 5> arr = {1, 2, 3, 4, 5};
    int i = 0;
    const size_t n = arr.size();
    
start_loop:
    if (i >= n)
        goto end_loop;

    std::cout << arr[i] << " ";
    i++;
    goto start_loop;

end_loop:
    return 0;
}

5. Iterator-based for loop #

Works with any container that supports begin() and end() methods. This includes C-style arrays.

#include <iostream>

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    for (auto it = std::begin(arr); it != std::end(arr); ++it)
    {
        std::cout << *it << " ";
    }
    return 0;
}

6. Range-based for loop #

The recommended and modern way of iterating a container. It’s safe, clean and works with any container that supports begin() and end().

#include <iostream>

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    for (int val : arr)
    {
        std::cout << val << " ";
    }
    return 0;
}

7. Functional style #

In this example, we use for_each from the <algorithm> header. This approach allows you to pass a lambda function or a function pointer to be executed for each element in the range.

#include <iostream>
#include <algorithm>

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    std::for_each(std::begin(arr), std::end(arr), [](int n) 
    {
        std::cout << n << " ";
    });
    return 0;
}

8. Recursion #

It’s rarely used in practice, but it can be discussed in theoretical contexts.

#include <iostream>

void iterate(int* ptr, size_t size)
{
    if (size == 0) return;
    std::cout << *ptr << " ";
    iterate(ptr + 1, size - 1);
}

int main()
{
    int arr[] = {1, 2, 3, 4, 5};
    iterate(arr, 5);
    return 0;
}