Read-only ranged based for

228 Views Asked by At

Let us consider the following example (of course this should be replaced by std::accumulate):

#include <vector>

auto sum(std::vector<int> const& numbers) -> int
{
    auto sum = 0;
    for(auto /*const, const&, &&, [nothing]*/ i : numbers) { sum += i; }
    return sum;
}

As you see, there are many different ways to use the ranged-based for loop for small types. Note that all of these variants compiled to the same assembly code in compiler explorer using gcc.

I often see the recommendation to use auto i in the first case and auto const& i in the second case.

But we are talking to the compiler and not the human here. The interesting information is that the variable is only input. This is not expressed by auto i.

So is there any performance-disadvantage of using auto const& i instead of auto i in any situation where you only need to read the input?

3

There are 3 best solutions below

2
On BEST ANSWER

Do not overthink this. In C and C++ there is "AS IF RULE" which causes that any version of your example doesn't lead to any changes in resulting machine code.

See this godbolt: https://godbolt.org/z/3rnWrr Explenation: note each compiler command line arguments is defining VERSION macro, to provide auto, auto& or auto const &.

So basically if vector contains simple type (like build ins) just use auto since it is more convenient. In other case with complex types, you need to think about it a bit more and decide between auto and auto&. If have doubts do some measurements or check assembly.

3
On

The new loop style looks easy, but there are some pitfalls to avoid, like everywhere in C++:

You have four ways to declare your loop variable to choose from:

auto i

Creates a writable copy of the item. Writes to that item are lost because it is only a copy and not the original item. Always avoid this version!

auto const i

Creates a read only copy. Copying complex types can be very costly, so avoid this one, too

auto &i

Creates a writable reference. Use this version only when you want to modify the item.

auto const& i

Creates a read only reference to the item. Use this one always when the item is not modified. This is the most commen form, please get used to it.

0
On

Likely, there is no performance-disadvantage of using auto const& i instead of auto i in your example above. The compiler may be able to optimize the reference away in cases where the type is a relative small type.

When you compile both versions you can inspect the generated code to see whether the compiler generated the same code or not. Then you know what your compiler does

See also Will a good C++ compiler optimize a reference away? .