C++11新特性——range for

很多编程语言都有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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏决胜机器学习

PHP数据结构(六) ——数组的相乘、广义表

PHP数据结构(六)——数组的相乘、广义表 (原创内容,转载请注明来源,谢谢) 本文接PHP数据结构(五)的内容。 4.2 行逻辑链接的顺序表 行逻辑链接的顺...

4259
来自专栏机器之心

入门 | 数据科学初学者必知的NumPy基础知识

选自TowardsDataScience 作者:Ehi Aigiomawu 机器之心编译 参与:李诗萌、路 本文介绍了一些 NumPy 基础知识,适合数据科学初...

2763
来自专栏尾尾部落

[剑指offer] 调整数组顺序使奇数位于偶数前面

输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相...

932
来自专栏数据结构与算法

洛谷P1067 多项式输出(模拟)

题目描述 一元 n 次多项式可用如下的表达式表示: ? 其中,aixi称为 i 次项,ai 称为 i 次项的系数。给出一个一元多项式各项的次数和系数,请按照如下...

2785
来自专栏desperate633

LintCode 搜索插入位置题目分析代码

给定一个排序数组和一个目标值,如果在数组中找到目标值则返回索引。如果没有,返回到它将会被按顺序插入的位置。 你可以假设在数组中无重复元素。

742
来自专栏小樱的经验随笔

平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。

题目:平面上给定n条线段,找出一个点,使这个点到这n条线段的距离和最小。 源码如下: 1 #include <iostream> 2 #include ...

2604
来自专栏Python小屋

使用Python列表实现向量运算

在Python中,列表支持与整数的乘法运算,但表示的是列表元素的重复,并生成新列表,如: >>> [1,2,3]*3 [1, 2, 3, 1, 2, 3, 1...

4546
来自专栏Petrichor的专栏

numpy: np.random模块 探究(源码)

2032
来自专栏Python小屋

详解Python列表推导式

列表推导式,也叫列表解析式,英文名称为list comprehension,可以使用非常简洁的方式来快速生成满足特定需求的列表,代码具有非常强的可读性。另外,P...

3254
来自专栏tkokof 的技术,小趣及杂念

编程小知识之 Random接口返回值

平日工作中,(伪)随机数的使用一定是避不开的,拿 C# 为例,System 命名空间下的 Random 类型一般都是我们生成(伪)随机数的第一选择:

933

扫码关注云+社区