游戏引擎微优化情况:我正在使用C ++ 11 range for循环使用vector<int>
关键字迭代auto
。
什么更快:
for(auto value : ints) ...
或
for(auto& value : ints) ...
答案 0 :(得分:12)
在关心哪个更快之前,你应该关心哪个在语义上是正确的。如果您不需要更改正在迭代的元素,则应选择第一个版本。否则,您应该选择第二个版本。
当然,您可以反对即使您不需要更改向量的内容,仍然可以选择使用对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)
。
我不认为性能会更差(相反,我希望它会更好),但是在性能方面总是如此,支持您的假设的唯一有意义的方法是衡量,衡量和衡量。 / p>
答案 1 :(得分:5)
如果您修改value
并希望它修改您需要 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 . . .
我不会在这里读到时差。出于所有实际目的,它们是相同的,并且稍微波动以便运行。
答案 2 :(得分:2)
首先,如果要修改值使用auto&
,如果不是 - 请不要。因为你可能会意外地改变它。
但可以在const auto&
和简单auto
之间进行选择。对于std::vector<int>
,我认为这里的性能不是问题。
为什么要使用auto
vector
)为什么要使用const auto&
在这两种情况下,您应该了解您的工作。这可能取决于循环是否以某种方式修改了我们的范围。
答案 3 :(得分:2)
在GCC中,两个版本都使用优化标记-O1
到-O3
编译到同一个程序集。
由于编译器会为您处理优化,因此只要您不需要更改值,我就会使用for (auto value : ints)
。正如Andy指出的那样,你可以使用const-refs,但如果没有任何性能提升,那么我就不会打扰了。