6

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) ...

?

4

4 回答 4

14

在关心哪个更快之前,您应该关心哪个在语义上是正确的。如果你不需要改变被迭代的元素,你应该选择第一个版本。否则,您应该选择第二个版本。

当然,您可以反对即使您不需要更改向量的内容,仍然可以选择使用对 的引用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)这就是说,对于基本类型,只要这在语义上是正确的,我就会使用。

我不认为性能会更差(相反,我希望它会更好),但与往常一样,在性能方面,支持你的假设的唯一有意义的方法是测量、测量和测量。

于 2013-05-13T14:11:28.573 回答
5

如果您修改并期望它修改您需要value的向量中的实际元素。如果您不修改它,它可能会编译成与or完全相同的代码(对其进行分析以自行查找)。 auto&valueautoauto&

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

我不会在这里阅读时差。出于所有实际目的,它们是相同的,并且在运行中略有波动。

于 2013-05-13T14:09:02.030 回答
2

首先,如果你要修改 value use auto&,如果不是 - 不要。因为你可能会不小心改变它。

const auto&但是在和简单之间可能会有选择auto。我相信性能在这里不是问题,因为std::vector<int>.

为什么使用auto

  1. 它更容易阅读
  2. 它允许改变它(不改变vector

为什么使用const auto&

  1. 它应该与其他类型一起使用,因此这样写更通用。此外,如果您将类型更改为任何复杂的类型,您也不会意外遇到性能问题。
  2. 它不允许更改此变量的值,因此可能会在编译时捕获一些错误。

在这两种情况下,您都应该了解您在做什么。这可能取决于循环是否以某种方式修改了我们的范围。

于 2013-05-13T14:11:40.670 回答
2

在 GCC 中,两个版本都-O1通过-O3.

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

于 2013-05-13T14:28:21.630 回答