向量<int>上的Foreach范围迭代 - auto或auto&amp;?</int>

时间:2013-05-13 14:05:41

标签: c++ performance c++11 foreach auto

游戏引擎微优化情况:我正在使用C ++ 11 range for循环使用vector<int>关键字迭代auto

什么更快:

for(auto value : ints) ...

for(auto& value : ints) ...

4 个答案:

答案 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,则可能会使用autoauto&编译完全相同的代码(将其设置为自行查找)。

我使用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

  1. 更容易阅读
  2. 允许更改它(不更改vector
  3. 为什么要使用const auto&

    1. 它应该与其他类型一起使用,因此以这种方式编写更通用。此外,如果您将类型更改为任何复杂类型,则不会意外地出现性能问题。
    2. 它不允许更改此变量的值,因此可能会在编译时捕获一些错误。
    3. 在这两种情况下,您应该了解您的工作。这可能取决于循环是否以某种方式修改了我们的范围。

答案 3 :(得分:2)

在GCC中,两个版本都使用优化标记-O1-O3编译到同一个程序集。

由于编译器会为您处理优化,因此只要您不需要更改值,我就会使用for (auto value : ints)。正如Andy指出的那样,你可以使用const-refs,但如果没有任何性能提升,那么我就不会打扰了。