基于范围的 for 循环 (C++11 起)

来自cppreference.com
< cpp‎ | language

在范围上执行 for 循环。

用作传统for 循环的更加可读的等价物,在操作一个范围的值时,例如一个容器中的所有元素。

目录

[编辑] 语法

attr(可选) for ( range_declaration : range_expression ) loop_statement
attr - 任何数量的属性
range_declaration - 一个具名变量的声明,其类型是由 range_expression 所表示的序列的元素的类型,或到该类型的引用。通常由于自动类型推导而用 auto 指定符
range_expression - 任何表示一个适合序列(数组或定义了 beginend 成员函数或自由函数的对象之一,见后述)的表达式或一个花括号初始化列表
loop_statement - 任何语句,典型的是一条符合语句,它是循环体

range_declaration 可以是结构化绑定声明

for (auto&& [first,second] : mymap) {
    // use first and second
}
(C++17 起)

[编辑] 解释

上述语法产生的代码等价于下列内容(__range__begin__end 仅为说明):

{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}

}

(C++17 前)
{
auto && __range = range_expression ;
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}

}

(C++17 起)

range_expression 被求值以确定要迭代的序列或范围。继而序列的每个元素,会被解引用以赋值给拥有 range_declaration 所给定类型和名称的变量。

begin_exprend_expr 定义如下:

  • range_expression 是数组类型表达式,则 begin_expr__rangeend_expr(__range + __bound) ,其中 __bound 是数组的元素数目(若数组大小未知或拥有不完整类型,则程序为病态)
  • range_expression 是拥有名为 begin 和/或 end 成员的类类型 C 的表达式(不管该成员的类型或可见性),则 begin_expr__range.begin()end_expr__range.end()
  • 否则, begin_exprbegin(__range)end_exprend(__range) ,通过参数依赖查找寻找(不进行非 ADL 查找)。

range_expression 返回临时量,则其生存期被延续到循环结尾,如同绑定到右值引用 __range 所示,但要注意 range_expression 中任何临时量生存期都不被延长。

正如传统循环, break 语句可用于提早退出循环,且 continue 语句能用于以下个元素重新开始循环。

attr 表示可选数量的属性

[编辑] 注意

若初始化器( range_expression )是花括号初始化列表,则 __range 被推导为 std::initializer_list<>&&

使用推导到转发引用, for (auto&& var : sequence) ,是安全的,且在通用代码中更适合。

任何名为 beginend 成员的存在,无关乎它是类型、数据成员、函数或枚举项,且无关乎其可访问性,将导致 __range.begin()__range.end() 被各自用作 begin_exprend_expr 。结果,基于范围的 for 循环不能用于含有名为 beginend 的类型或枚举项的类,即使提供了适当命名空间的自由函数。

虽然声明于 range_declaration 的变量通常在 loop_statement 中使用,但不强制这么做。

从 C++17 开始, begin-expression 和 end-expression 不必拥有相同类型,而且实际上 end-expression 的类型不必是迭代器:它只需能与一个迭代器比较不等。这使得以谓词分界可能(例如“迭代器指向空字符”)。

[编辑] 关键词

for

[编辑] 示例

#include <iostream>
#include <vector>
 
int main() {
    std::vector<int> v = {0, 1, 2, 3, 4, 5};
 
    for (const int& i : v) // 以 const 引用访问
        std::cout << i << ' ';
    std::cout << '\n';
 
    for (auto i : v) // 以值访问, i 的类型是 int
        std::cout << i << ' ';
    std::cout << '\n';
 
    for (auto&& i : v) // 以引用访问, i 的类型是 int&
        std::cout << i << ' ';
    std::cout << '\n';
 
    for (int n : {0, 1, 2, 3, 4, 5}) // 初始化器可以是花括号初始化列表
        std::cout << n << ' ';
    std::cout << '\n';
 
    int a[] = {0, 1, 2, 3, 4, 5};
    for (int n : a) // 初始化器可以是数组
        std::cout << n << ' ';
    std::cout << '\n';
 
    for (int n : a)  
        std::cout << 1 << ' '; // 循环变量不必使用
    std::cout << '\n';
 
}

输出:

0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
0 1 2 3 4 5
1 1 1 1 1 1

[编辑] 参阅

将一个函数应用于某一范围的元素
(函数模板) [编辑]