很多编程语言都有range for语法功能,自C++11起,终于将这个重要功能加入C++标准中。range for语句,可以方便的遍历给定序列中的每个元素并对其执行某种操作。

1.基本语法

for(declaration:expression)
    statement

其中,declaration定义一个变量,该变量将被用于访问序列中的基础元素,每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。expression是一个对象,用于表示一个序列。statement是对序列中元素的操作。

2.示例

vector<int> vec{1,2,3}; //C++11 only,大括号初始化
for (int i : vec )
    cout << i;

上面的操作时将vector数组中的元素拷贝至变量i中,进行输出。如果想改变vector数组中的元素值,需要把循环变量i定义成引用类型,实现如下:

vector<int> vec{1,2,3}; //C++11 only,大括号初始化
for (auto& i : vec ){
    i=i*i;
    cout << i;
}
//输出结果:149

请注意,我们依然可以用continue语句来开始下一次迭代,使用break跳出循环,这一点和普通的for循环一样。

3.深入分析

range for语句实际上等价于如下语句:

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

请注意,“等价于”并不表示编译器就是这么实现range for,只是说两者的运行效果等价。其中expression是被迭代的对象, begin_expr与end_expr是迭代对象的迭代器,取值有:

(1)对于数组类型 begin_expr和end_expr分别等于__range和__range + __bound;

(2)对于STL中的容器,两者分别等于__range.begin()和__range.end();

(3)对于其他类型,两者分别等于begin(__range)和end(__range)。编译器将会通过参数类型来找到合适的begin和end函数。

4.让自定义的类可以迭代

通过range for的等价语句可以看出,只要符合一定要求,自己定义的类也可以放在其中进行迭代。事实上要想进行迭代,一个类需要满足以下条件:

(1)拥有begin和end函数,返回值是一个可以自己定义的迭代器,分别指向第一个元素和最后一个元素。既可以是成员函数,也可以是非成员函数。

(2)迭代器本身支持*、++、!=运算符,既可以是成员函数,也可以是非成员函数。

示例如下:

#include <stdlib.h>
#include <iostream>
using namespace std;

class IntVector{
    //迭代器类
    class Iter{
    public:
        Iter(IntVector* p_vec, int pos):_pos(pos),_p_vec(p_vec){}

        // these three methods form the basis of an iterator for use with range for
        bool operator!= (const Iter& other) const{
            return _pos != other._pos;
        }

        // this method must be defined after the definition of IntVector,since it needs to use it
        int& operator*() const{
            return _p_vec->get(_pos);
        }

        const Iter& operator++ (){
            ++_pos;
            return *this;
        }

    private:
        IntVector *_p_vec;
        int _pos;
    };

public:
    IntVector(){}
    Iter begin(){
        return Iter(this,0);
    }
    Iter end(){
        return Iter(this, 20);
    }
    int& get(int col){
        return data[col];
    }
    void set(int index, int val){
        data[index] = val;
    }
private:
    int data[20] = {0};
};

int main() {
    IntVector v;
    for (int i = 0; i < 20; i++){
        v.set(i, i);
    }
    for (int& i : v) { i = i*i; cout << i <<" "; }
    system("pause");
}

程序输出结果:

0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 289 324 361

参考资料

[1]C++ Primer中文版(第5版)

[2]Range-based for loop (since C++11)

[3]C++11 新特性之Range-based for loops

C++11新特性——range for的更多相关文章

  1. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  2. C++ 11学习和掌握 ——《深入理解C++ 11:C++11新特性解析和应用》读书笔记(一)

    因为偶然的机会,在图书馆看到<深入理解C++ 11:C++11新特性解析和应用>这本书,大致扫下,受益匪浅,就果断借出来,对于其中的部分内容进行详读并亲自编程测试相关代码,也就有了整理写出 ...

  3. C++11新特性总结 (二)

    1. 范围for语句 C++11 引入了一种更为简单的for语句,这种for语句可以很方便的遍历容器或其他序列的所有元素 vector<int> vec = {1,2,3,4,5,6}; ...

  4. C++11新特性总结 (一)

    1. 概述 最近在看C++ Primer5 刚好看到一半,总结一下C++11里面确实加了很多新东西,如果没有任何了解,别说自己写了,看别人写的代码估计都会有些吃力.C++ Primer5是学习C++1 ...

  5. C++ 11 新特性

    C++11新特性:          1.auto          2.nullptr          3.for          4.lambda表达式          5.override ...

  6. [转载] C++11新特性

    C++11标准发布已有一段时间了, 维基百科上有对C++11新标准的变化和C++11新特性介绍的文章. 我是一名C++程序员,非常想了解一下C++11. 英文版的维基百科看起来非常费劲,而中文版维基百 ...

  7. C++11新特性——大括号初始化

    C++11之前,C++主要有以下几种初始化方式: //小括号初始化 string str("hello"); //等号初始化 string str="hello" ...

  8. C++11新特性之六——元编程

    C++11新特性之六——元编程

  9. C++11新特性之一——Lambda表达式

    C++11新特性总结可以参考:http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html#section_6.8 C++ ...

随机推荐

  1. .Net Core Cookie-Based认证与授权

    .Net Core的其中一种认证与授权模式是基于Cookie的,首先我们先创建一个.Net Core MVC 项目: 然后增加对页面访问的权限控制,对要访问的页面Conytroller增加Author ...

  2. [朴孝敏][Ooh La La]

    歌词来源:http://music.163.com/#/song?id=484058960 作曲 : Damon Sharpe/Jimmy Burney/Adam Kapit [作曲 : Damon ...

  3. Docker容器学习梳理 - 容器登陆方法梳理(attach、exec、nsenter)

    对于运行在后台的Docker容器,我们运维人员时常是有登陆进去的需求.登陆Docker容器的方式:1)使用ssh登陆容器.这种方法需要在容器中启动sshd,存在开销和攻击面增大的问题.同时也违反了Do ...

  4. python基础学习笔记(一)

    安装与运行交互式解释器 在绝大多数linux和 UNIX系统安装中(包括Mac OS X),Python的解释器就已经存在了.我们可以在提示符下输入python命令进行验证(作者环境ubuntu) f ...

  5. Python_初识函数和返回值_22

    #len s = '金老板小护士' len(s) def my_len(): #自定义函数 i = 0 for k in s: i += 1 print(i) length = my_len() pr ...

  6. 898 C. Phone Numbers

    传送门 [http://codeforces.com/contest/898/problem/C] 题意 题意比较难理解直接看样例就知道了,给你个n接下来n行,每行包括一个名字和号码的数量,还有具体的 ...

  7. [BUAA软工]第一次博客作业---阅读《构建之法》

    [BUAA软工]第一次博客作业 项目 内容 这个作业属于哪个课程 北航软工 这个作业的要求在哪里 第1次个人作业 我在这个课程的目标是 学习如何以团队的形式开发软件,提升个人软件开发能力 这个作业在哪 ...

  8. HDOJ2017_字符串统计

    这是一道水题 HDOJ2017_字符串统计 #include<iostream> #include<string> #include<stdio.h> #inclu ...

  9. [2017BUAA软工]个人项目

    软工个人项目 一.Github项目地址 https://github.com/Lydia-yang/2017BUAA-SoftwareEngineering 二.解题思路 在刚开始拿到题目的时候,关于 ...

  10. 【转】七牛免费SSL证书,配置自定义域名CDN加速

    原文链接:https://excaliburhan.com/post/use-qiniu-ssl-and-cdn.html 申请七牛SSL证书 其实,七牛在很早之前就支持CDN使用https,但是他要 ...