zoukankan      html  css  js  c++  java
  • 使用基于范围的 for 循环迭代范围

    特别声明:
    本文翻译自 Modern C++ Programming Cookbook 一书中的“Learning Modern Core Language Features”章节中的“Using range-based for loops to iterate on a range”小节。
    翻译此文纯粹作为学习之用,版权归原作者及出版社所有。

    许多编程语言支持 for 循环的称之为 for each 的变体,即针对集合中的元素重复一组语句。在 C++11 之前 C++没有相应的核心语言支持。最接近的特性是来自标准库中的被称为 std::for_each 的通用算法,它在范围的所有元素上应用一个函数。C++11 带来了对 for each 的语言级支持,实际称之为基于范围 for 循环。新的 C++17 标准对原始语言特性提供了一些改进。

    Getting ready

    在 C++11 中,基于范围 for 循环的通用语法如下:

    1for (range_declaration : range_expression) loop_statement

    为了举例说明基于范围的 for 循环的不同用法,我们将使用下面这些函数返回元素序列:

     1std::vector<int> getRates()
    2{
    3    return std::vector<int>{11235813};
    4}
    5
    6std::multimap<intbool> getRates2()
    7{
    8    return std::multimap<intbool>{
    9        {1true},
    10        {1true},
    11        {2false},
    12        {3true},
    13        {5true},
    14        {8false},
    15        {13true}
    16      };
    17}

    How to do it…

    基于范围的 for 循环可以通过不同的方式使用:

    • 为序列元素提供一个特定类型:
    1auto rates = getRates();
    2for (int rate : rates)
    3    std::cout << rate << std::endl;
    4
    5for (int &rate : rates)
    6    rate *= 2;
    • 不指定类型并由编译器进行推导:
    1for (auto &&rate : getRates())
    2    std::cout << rate << std::endl;
    3
    4for (auto &rate : rates)
    5    rate *= 2;
    6
    7for (auto const &rate : rates)
    8    std::cout << rate << std::endl;
    • 在 C++17 中,通过使用结构化绑定和解构声明:
    1for (auto &&[rate, flag] : getRates2())
    2    std::cout << rate << std::endl;

    How it works…

    之前在 How to do it… 中显示的基于范围的 for 循环的表达式是基础的语法糖,编译器会将其转换为其它的东西。在 C++17 之前,编译器生成的代码如下所示:

    1{
    2    auto &&__range = range_expression;
    3    for (auto __begin = begin_expr, __end = end_expr;
    4         __begin != __end; ++__begin)
    5    {
    6        range_declaration = *__begin;
    7        loop_statement
    8    }
    9}

    代码中的 begin_expr 和 end_expr 依赖于这个范围的类型:

    • 对于 C 风格的数组,__range 和 __bound 是数组中元素的个数。
    • 对于有 begin() 和 end() 成员的类类型(无论它们的类型和可访问性):__range.begin() 和 __range.end()。
    • 对于其它类型是 begin(__range) 和 end(__range),通过参数依赖查找进行确定。

    需要注意的是,如果一个类包含名为 begin 或 end 的任何成员(函数,数据成员或枚举器),无论它们的类型和可访问性,它们都将被选为 begin_expr 和 end_expr。因此,这样的类类型不能使用基于范围 for 循环。

    在 C++17 中,编译器生成的代码略微不同:

     1{
    2    auto &&__range = range_expression;
    3    auto __begin = begin_expr;
    4    auto __end = end_expr;
    5    for (; __begin != __end; ++__begin)
    6    {
    7        range_declaration = *__begin;
    8        loop_statement
    9    }
    10}

    新标准移除了 begin 表达式和 end 表达式必须拥有同一类型的约束。end 表达式不再需要是一个实际的迭代器,但是它必须能够与迭代器进行不等式比较。

    这样做的好处是范围可以由谓词分隔。

    See also

    • 为自定义类型启用基于范围的 for 循环

    - - - End - - -


    欢迎扫码订阅我的微信公众号,阅读其它相关文章。
    欢迎扫码订阅我的微信公众号,阅读其它相关文章。

    本文作者: Lzl678
    本文链接: https://www.cnblogs.com/Lzl678/p/10940182.html
    版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!

  • 相关阅读:
    CentOS 7.4 如何安装 MariaDB 10.3.9 Stable 数据库
    xxx is not in the sudoers file. This incident will be reported.
    CentOS 7.4 上如何安装 tomcat 9
    CentOS 7.4 下面安装 jdk 10 的一点总结
    CentOS 7.4 下安装 Nginx
    MySQL数据库常用操作
    chart学习
    Ext需要的文件目录
    获取浏览器信息
    运行容器
  • 原文地址:https://www.cnblogs.com/Lzl678/p/10940182.html
Copyright © 2011-2022 走看看