这段代码会在每次迭代中获取元素吗?

Would this code fetch the elements every iteration?

本文关键字:迭代 获取 元素 段代码 代码      更新时间:2023-10-16

通常情况下,我会这样写代码。

auto elements = get_elements();
for(auto i : elements)
{
    // ...
}

我想知道使用下面的代码是否会产生任何性能差异。get_elements()是每次迭代都被调用还是只调用一次?

for(auto i : get_elements())
{
    // ...
}

此外,传统的for循环呢?如果我不修改我循环的元素,编译器会优化代码不调用get_elements()每次迭代吗?

for(auto i = get_elements().begin(); i != get_elements().end(); ++i)
{
    // ...
}

我想知道使用下面的代码是否会使性能有所不同

与往常一样,当涉及到性能时,您应该用测量来支持您的假设。

没有其他证据表明在特定例程中存在瓶颈,这应该成为放弃更清晰,更简单的设计而支持更复杂,更不直观的设计的理由。根据定义,这将是过早优化

因此,选择最能传达其意图的形式。这就是说,我可以回答以下问题:

每次迭代都调用get_elements()还是只调用一次?

,它只会被调用一次。c++ 11标准第6.5.4/1段规定了这种行为:

对于形式为

的基于范围的For语句
for ( for-range-declaration : expression ) statement

range-init等价于括号

中的表达式
( expression )

[…一个基于范围的for语句是等价的

{
    auto && __range = range-init; // <== HERE IS YOUR get_elements()!
    for ( auto __begin = begin-expr,
        __end = end-expr;    
        __begin != __end;
        ++__begin ) {
            for-range-declaration = *__begin;
            statement
        }
    }

关于你的第二个问题:

此外,传统的for循环呢?

这些只是不太清楚循环本身的目的,更容易出错。我建议避免手动循环。

例如,只看它的第一行,就可以明显看出基于范围的for循环的目的是遍历集合的所有元素。

对于手动展开的for循环来说,同样的情况并不明显,仅通过查看第一行,您不知道i变量是否会在循环内被增加或操作。

Herb Sutter在这篇文章中对此进行了很好的讨论(参见问题2-a的解决方案)。