【问题标题】:Would this code fetch the elements every iteration?这段代码会在每次迭代时获取元素吗?
【发布时间】:2013-05-17 11:32:25
【问题描述】:

通常,我会编写这样的代码。

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)
{
    // ...
}

【问题讨论】:

    标签: c++ performance loops call iteration


    【解决方案1】:

    我想知道改用下面的代码是否会对性能产生任何影响

    与往常一样,在性能方面,您应该通过测量来支持您的假设。

    除了明确的测量表明您在该特定例程中存在瓶颈之外,没有其他证据可以成为放弃更清晰、更简单的设计而转而采用更复杂、更不直观的设计的理由。根据定义,这将是过早的优化

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

    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 变量是否会在循环内递增或被操纵。

    this article by Herb Sutter 对此进行了很好的讨论(请参阅问题 2-a 的解决方案)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-30
      • 1970-01-01
      相关资源
      最近更新 更多