“for (x : y)”是什么?

6

我正在网上寻找关于线程的内容,偶然发现了一篇关于线程的博客/教程,但是有一句话让我感到困惑:

for (auto& thread : threads)  

我不太确定那个是做什么的
这是我所提到的博客链接 LINK
感谢任何回答我的问题的人
附注:你能否也给我一个参考资料,让我可以了解它的作用以及其他相关的事情?当我搜索时似乎眼盲了


这是一个特殊结构的一部分 - 标题编辑应该明确说明哪个。 - user2864740
5
它不是一个运算符。请参考a reference。顺便说一句,看起来for (thread : threads)在C++17中将成为可能。 - chris
这是一个基于范围的for循环。例如,请参见现有的https://dev59.com/y2w05IYBdhLWcg3w41y5 - Keith
你是在指 基于范围的 for 循环 吗? - Khouri Giordano
2
互联网和博客并不是好的C++教程。 - Kerrek SB
@KhouriGiordano 根据其他人的说法似乎是这样 个人从未见过,所以我的第一个猜测是它是某种运算符。 - TheKingOfAtlantis
2个回答

13

C++11引入了一种新的迭代语句,称为所谓的基于范围的for循环。它不同于普通的for循环,它只给出了访问范围成员的权限,而不需要显式地命名范围本身或使用代理迭代器对象。具体来说,在迭代过程中不应该改变范围,因此这个新循环记录了"查看每个范围元素"的意图,而不对范围本身进行复杂操作。

语法是这样的:for (decl x : r) { /* body */ },其中decl表示某个声明,r是任意表达式。这在功能上与传统的循环大致等效:

{
    auto && __r = r;

    using std::begin;
    using std::end;

    for (auto __it = begin(__r), __e = end(__r); __it != __e; ++__it)
    {
        decl x = *it;
        /* body */
    }
}

作为一种特殊情况,数组和花括号列表也被本地支持。


主要的区别在于:(1)它实际上并没有使用std::beginstd::end,因此不需要包含<iterator>;(2)它不执行非成员beginend的普通未限定名称查找,只执行ADL。 - T.C.
“在迭代过程中,您不应该改变范围”的意思是什么?这是您个人的规则吗?您几乎让它听起来好像这样做是未定义行为。” - Benjamin Lindley
1
@BenjaminLindley:循环的“等效形式”使得如果你使迭代器无效,那么你很可能会遇到麻烦。你或许可以设计一些不会导致未定义行为的范围变异,但这将是极其令人惊讶的,而且永远不是你想要的结果。如果你想在遍历时改变范围,请使用普通的for循环。 - Kerrek SB
我觉得我误解了你的意思。我以为你是在说,不应该改变(即调用非const函数)范围内的单个元素。 - Benjamin Lindley
@BenjaminLindley:没错。当然,您可以随意处理元素。但是,在循环内部时,您永远无法看到元素来自哪里,这是它在可读性方面的关键优势之一。 - Kerrek SB
C++17 中还有一点细微的差别:beginend 被用于分开的声明语句,而且不再需要拥有相同的类型。 - aschepler

2
这是一个基于C++11的范围循环,需要使用范围表达式,可以是以下之一:
  • 数组或
  • 用大括号包含的列表
  • 具有以下任一属性的类
    • 成员函数 begin()end()
    • 可通过ADL获得的自由函数 begin()end()

这个

for ( for_range_declaration : expression ) statement;

扩展为

range_init = (expression)
{
  auto && __range = range_init;
  for ( auto __begin = begin_expr,
  __end = end_expr;
  __begin != __end;
  ++__begin ) {
    for_range_declaration = *__begin;
    statement;
  }
}

其中begin_expr和end_expr是通过数组检查或begin()/end()对获取的。(这里的statement可以是带花括号的复合语句。)


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