【问题标题】:Range-based for loop equivalent基于范围的 for 循环等效
【发布时间】:2014-01-12 12:42:14
【问题描述】:

所以根据n2243,基于范围的for循环等价于:

{
     auto && __range = ( expression );

     for ( auto __begin = std::Range<_RangeT>::begin(__range),
                  __end = std::Range<_RangeT>::end(__range);
          __begin != __end;
          ++__begin )
     {
         for-range-declaration = *__begin;
         statement
     }    
}

然后它显示2 If the header &lt;iterator_concept&gt; is not included prior to a use of the range-based for statement, the program is ill-formed.,所以我质疑这是最新的。我也很好奇std::Range 是什么,或者它是否纯粹是一个实现细节。我能找到的最接近的是n3350

这个answer 依赖此信息并说:

Range for 尽可能快,因为它缓存了结尾 iterator[citation],使用预增量并且只取消引用 迭代一次。

所以如果你倾向于写作:

for(iterator i = cont.begin(); i != cont.end(); i++) { /**/ }

那么,是的,range-for 可能会稍微快一些,因为它也更容易 写下没有理由不使用它(在适当的时候)。

附:我说它尽可能快,但它并不比 可能的。如果你写你的,你可以达到完全相同的性能 仔细手动循环。

我很好奇它现在是否真的有所作为。据我所知,它只是语法糖。例如,在可以执行auto it = s.rbegin(); it != s.rend(); ++it 的循环中,它需要返回反向迭代器的样板代码,其中基于范围的for 循环需要beginend。如果它节省的只是打字,那么它还提供什么其他优势,因为它需要beginend?我很好奇我上面引用的答案是否仍然有效,因为这篇论文是 2007 年的。

【问题讨论】:

  • 这个提案(N2243)已经很老了(是这个话题的第二个吗?),已经多次修改。我能找到的关于它的最新个人论文是N2930,在N3257 中讨论了一个缺陷。考虑使用N3337 或标准本身作为它现在定义的来源。 std::Range 部分已被替换。

标签: c++ c++11 for-loop


【解决方案1】:

正如@DyP 所说,这部分在最终标准中有所改变。 C++11 6.5.4 基于范围的for 语句[stmt.ranged]:

1 对于基于范围的for 形式的语句

  for ( for-range-declaration : expression ) statement

range-init 等价于括号括起来的表达式

  ( expression )

对于基于范围的for 形式的声明

  for ( for-range-declaration : braced-init-list ) statement

range-init 等价于 braced-init-list。在每种情况下,基于范围的for 语句都等效于

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

其中__range__begin__end 是仅为说明定义的变量,_RangeT 是表达式的类型,而 begin-exprend -expr 确定如下:

  • 如果_RangeT是数组类型,begin-exprend-expr分别是__range__range + __bound,其中@987654337 @ 是数组绑定。如果_RangeT是一个未知大小的数组或者一个不完整类型的数组,则程序是非良构的;

  • 如果_RangeT 是类类型,则unqualified-ids beginend 在类_RangeT 的范围内查找,就像通过类成员访问一样查找 (3.4.5),如果其中一个(或两者)找到至少一个声明,begin-exprend-expr 分别是 __range.begin()__range.end()

  • 否则,begin-exprend-expr 分别为 begin(__range)end(__range),其中查看 beginend使用依赖于参数的查找(3.4.2)。出于此名称查找的目的, 命名空间std 是一个关联的命名空间。

[示例:

  int array[5] = { 1, 2, 3, 4, 5 };
  for (int& x : array)
    x *= 2;

——结束示例]

2 在 for-range-declarationdecl-specifier-seq 中,每个 decl-specifier 应该是一个 类型说明符constexpr

【讨论】:

  • 这也提出了一个问题,如果已经有一些标准草稿的来源,格式为 SO 兼容的 Markdown/HTML(可能来自乳胶来源?);)
  • @DyP 那太不可思议了,我们应该启动一个项目来实现一个翻译器。
  • 我想我撤回了关于 blockquote 的评论。它并没有完全提高可读性.. 至于降价:快速谷歌搜索出现了Pandoc,可以尝试一下(它也在 GPL 下)。
  • @DyP 我认为没有白色和灰色的分离会更好。
猜你喜欢
  • 2016-10-31
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
  • 2013-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多