Warning C26817

Potentially expensive copy of variable name in range-for loop. Consider making it a const reference (es.71).

For more information, see ES.71 notes in the C++ Core Guidelines.

Example

If a range-for loop variable isn't explicitly marked as a reference, it gets a copy of each element iterated over:

#include <vector>

class MyComplexType {
    int native_array[1000];
    // ...
};

void expensive_function(std::vector<MyComplexType>& complex_vector_ref)
{
    for (auto item: complex_vector_ref)
    {
        // At each iteration, item gets a copy of the next element
        // ...
    }
    for (MyComplexType item: complex_vector_ref)
    {
        // It happens whether you use the auto keyword or the type name
        // ...
    }
}

This behavior is fine for scalars (pointers, arithmetic types, and so on), but for larger types, the copying may become expensive.

Solution

To fix this issue, if the loop variable isn't mutated anywhere in the loop, make it a const reference:

#include <vector>

class MyComplexType {
    int native_array[1000];
    // ...
};

void less_expensive_function(std::vector<MyComplexType>& complex_vector_ref)
{
    for (const auto& item: complex_vector_ref)
    {
        // item no longer gets a copy of each iterated element
        // ...
    }
    for (const MyComplexType& item: complex_vector_ref)
    {
        // item no longer gets a copy of each iterated element
        // ...
    }
}

The const keyword makes the loop variable immutable. Use of a non-const reference may cause potentially unwanted side effects in the original container elements. If you need to modify only the local loop variable, the potentially expensive copying is unavoidable.