Game engine micro-optimization situation: I'm using C++11 range for loop to iterate over a vector<int>
, with the auto
keyword.
What is faster:
for(auto value : ints) ...
or
for(auto& value : ints) ...
?
Before caring about which is faster, you should care about which is semantically correct. If you do not need to alter the element being iterated, you should choose the first version. Otherwise, you should choose the second version.
Sure, you could object that even if you do not need to alter the content of the vector, there is still the option to use a reference to const
:
for(auto const& value : ints)
And then the question becomes: Which is faster? By reference to const
or by value?
Well, again, you should first consider whether the above is semantically correct at all, and that 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 said, for fundamental types I would go with for (auto i : x)
whenever this 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 meaningful way to back up your assumptions is to measure, measure, and measure.
If you modify value
and expect it to modify an actual element in the vector you need auto&
. If you don't modify value
it likely compiles into the exact same code with auto
or auto&
(profile it to find out for yourself).
I did some timing 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';
The 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 wouldn't read into the time differences here. For all practical purposes they are identical, and fluctuate slightly run to run.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With