C++11范围for循环的条件会在每个循环周期中被评估吗?

57
for(auto& entity : memoryManager.getItems()) entity->update(mFrameTime);
如果memoryManager包含1000个项,那么 memoryManager.getItems()被调用1000次还是只在循环开始时调用一次?
编译器是否会在-O2(或-O3)下运行任何优化?
memoryManager.getItems()返回一个std::vector<Entity*>&
1个回答

54

这只会被评估一次。标准将基于范围的for语句定义为等价于:

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

其中 : 后面的表达式(用括号括起来)或花括号初始化列表是 range-init 表达式。


1
几乎了。如果 : 右侧是一个表达式,那么 range-init 就是该表达式括在括号内的结果。 :) - Lightness Races in Orbit
3
确实如此。如果有人在意为什么这很重要,那是因为“这确保了顶层逗号运算符不能被重新解释为在声明__range时init-declarator之间的分隔符。” - Mike Seymour
1
range-init被评估一次时,++__begin将在每个循环中被评估,因此如果底层数据结构发生更改,则可能会将未在评估range-init时存在于底层数据结构中的值分配给for-range-declaration,包括导致未定义行为(例如,使迭代器失效)。只是澄清“评估一次”并不等同于在那个时间安全地生成所有值。 - Glenn Teitelbaum
@GlennTeitelbaum 谢谢,这是非常重要的澄清。 - Joe Todd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接