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) ...
?
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) ...
?
在关心哪个更快之前,您应该关心哪个在语义上是正确的。如果你不需要改变被迭代的元素,你应该选择第一个版本。否则,您应该选择第二个版本。
当然,您可以反对即使您不需要更改向量的内容,仍然可以选择使用对 的引用const
:
for(auto const& value : ints)
然后问题就变成了:哪个更快?通过引用const
还是通过值?
好吧,再一次,您应该首先考虑上述内容在语义上是否完全正确,这取决于您在for
循环中所做的事情:
int i = 0;
for (auto const& x : v) // Is this correct? Depends! (see the loop body)
{
v[i] = 42 + (++i);
std::cout << x;
}
for (auto i : x)
这就是说,对于基本类型,只要这在语义上是正确的,我就会使用。
我不认为性能会更差(相反,我希望它会更好),但与往常一样,在性能方面,支持你的假设的唯一有意义的方法是测量、测量和测量。
如果您修改并期望它修改您需要value
的向量中的实际元素。如果您不修改它,它可能会编译成与or完全相同的代码(对其进行分析以自行查找)。 auto&
value
auto
auto&
我使用 VS2012 和基于 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';
结果....
Count: 1700000000
auto& time: 77.0204
Count: 1700000000
const auto& time: 77.0648
Count: 1700000000
auto time: 77.5819
Press any key to continue . . .
我不会在这里阅读时差。出于所有实际目的,它们是相同的,并且在运行中略有波动。
首先,如果你要修改 value use auto&
,如果不是 - 不要。因为你可能会不小心改变它。
const auto&
但是在和简单之间可能会有选择auto
。我相信性能在这里不是问题,因为std::vector<int>
.
为什么使用auto
vector
)为什么使用const auto&
在这两种情况下,您都应该了解您在做什么。这可能取决于循环是否以某种方式修改了我们的范围。
在 GCC 中,两个版本都-O1
通过-O3
.
由于编译器会为您进行优化,因此for (auto value : ints)
只要您不需要更改值,我就会使用 。正如安迪指出的那样,您可以使用 const-refs,但如果没有任何性能提升,那么我就不会打扰。