Iteration of the Foreach range over the vector <int> - auto or auto &?

The situation with optimization in the game engine: I use the C ++ 11 range for the loop to iterate over vector<int> with the keyword auto .

Which is faster:

 for(auto value : ints) ... 

or

 for(auto& value : ints) ... 

?

+4
source share
4 answers

Before you care about which is faster, you should care about what is semantically correct. If you do not need to change the repeating element, you must select the first version. Otherwise, you must choose the second version.

Of course, you can argue that even if you do not need to change the contents of the vector, there is still the option to use a link to const :

  for(auto const& value : ints) 

And then the question arises: which is faster? With reference to const or by value?

Well, again, you should first consider whether this is semantically correct above, and it depends on what you are doing inside the for loop:

 int i = 0; for (auto const& x : v) // Is this correct? Depends! (see the loop body) { v[i] = 42 + (++i); std::cout << x; } 

This suggests that for the main types, I would go with for (auto i : x) whenever it is semantically correct.

I do not expect performance to be worse (rather, I expect it to be better), but, as always, when it comes to performance, the only significant way to back up your assumptions is to measure, measure, and measure.

+10
source

If you change the value and expect it to change the actual element in the vector, you need auto& . If you do not change the value , it is probably compiled into the same code using auto or auto& (profile to find out for yourself).

I have done several times using VS2012 with a timer based on QueryPerformanceCounter ...

  m::HighResTimer timer; std::vector<int> ints(100000000, 17); int count = 0; timer.Start(); for(auto& i : ints) count += i; timer.Stop(); std::cout << "Count: " << count << '\n' << "auto& time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n'; count = 0; timer.Reset(); timer.Start(); for(const auto& i : ints) count += i; timer.Stop(); std::cout << "Count: " << count << '\n' << "const auto& time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n'; count = 0; timer.Reset(); timer.Start(); for(auto i : ints) count += i; timer.Stop(); std::cout << "Count: " << count << '\n' << "auto time: " << duration_cast<duration<double, std::milli>>(timer.Elapsed()).count() << '\n'; 

Results....

 Count: 1700000000 auto& time: 77.0204 Count: 1700000000 const auto& time: 77.0648 Count: 1700000000 auto time: 77.5819 Press any key to continue . . . 

I would not read the time difference. For all practical purposes, they are identical and hesitate slightly to run.

+5
source

First of all, if you are going to change the value, use auto& , if not, do not. Because you can accidentally change it.

But there may be a choice between const auto& and simple auto . I believe that performance is not a problem here, for std::vector<int> .

Why use auto

  • Easier to read .
  • This allows you to change it (without changing the vector )

Why use const auto&

  • It should be used with another type, so it’s more typical to write this path. Moreover, if you change the type to any complex type, you will not accidentally get a performance problem.
  • This does not allow the value of this variable to be changed, so some errors may be captured at compile time.

In both cases, you must understand what you are doing . It may depend if the loop somehow changes our range.

+2
source

In GCC, both versions make up the same assembly with the optimization flags -O1 through -O3 .

Since the compiler will take care of the optimization for you, I would use for (auto value : ints) when you do not need to change the value. As Andy points out, you can use const-refs, but if you don't have performance, I would not bother.

+2
source

Source: https://habr.com/ru/post/1480492/


All Articles