C++11新特性-基于范围的for循环

来源:互联网 发布:mac有类似美图秀秀 编辑:程序博客网 时间:2024/05/18 00:30

C++11标准对语言引入了许多优秀的、有用的改进。我已经介绍了auto关键字,现在我再来说一下基于范围的for循环。怎样使用?怎样在你自己的类中使用?

1 基于范围的for循环的基本语法

现在,几乎每一个语言都能有一个非常方便的实现for循环的方法。C++也有类似的概念;你可以为你的for循环,添加一个container,他就会自动迭代。我们看下面的例子:

vector<int> vec;vec.push_back(10);vec.push_back(20);for (int i : vec){    cout << i;}

这段代码就是实现了对于vector型变量vec的内容打印,变量i遍历vector中的每一个元素,直到vector的结束。
当然了,在这里,为了迭代更加复杂的数据结构,你可以使用auto关键字。例如,迭代一个map类型数据变量,你可以这样写:

map<string, string> address_book;for (auto address_entry : address_book){    cout << address_entry.first << " < " address_entry.second << " > " << endl;}

编程人员就不需要担心要迭代类型的拼写了。

2 修改Vector内容

如果你想修改正在遍历的容器里的值,或者你想避免拷贝大量的对象,基本的迭代器就支持,你可以将循环变量作为引用调用。例如,对一个int型vector对象中每一个元素进行自加。

vector<int> vec;vec.push_back(1);vec.push_back(2);for(int& i : vec){    // 增加vector对象中元素的值    i++;    }for (int i : vec){    // 显示更新后的数值    cout << i << endl;}

3 基于范围是什么意思呢?

String,array和所有的STL容器类都能被这种新的基于范围的for循环迭代。但是,如果你将新语法应用到你自定义的数据结构上呢?
为了使一个数据具有可迭代性,他必须与STL迭代具有相似的工作属性。

  • (1)具有begin和end方法,即可以作为成员函数也可以作为独立的函数,函数返回数据结构开始和结束的迭代器。
  • (2)迭代器必须支持操作符*,!=,++,即可以作为成员函数也可作为独立函数(详细的信息可以参考操作符重载)。

在这里请注意,++操作符必须是前缀的,它被声明为不带参数的operator函数。

就是这样,用这五个函数,你就可以造一个数据结构,能够满足基于范围的for循环。但是begin()和end()方法是非成员函数(begin(container)代替container.begin()),你甚至可以为了适应已经存在的数据结构,不必刻意地支持STL类型的迭代器。你必须做的就是创建你自己的迭代器,它支持*(指针),前缀自加(++)和!=还要定义迭代器的begin和end,就可以了。

因为基于范围的循环是如此漂亮,我猜想那些不支持STL iterator的新容器类,都想添加一个适配器,去允许基于范围的for循环的。下面是一个小程序,创建一个简单的迭代器,然后实现基于范围的for循环。其中,首先创建IntVector类型,大小是100,可以被一个迭代器Iter迭代。代码如下:

// a simple iterator sample.#include <iostream>using namespace std;// forward-declaration to allow use in Iterclass IntVector;class Iter{private:    int _pos;    const IntVector *_p_vec;public:    Iter(const IntVector* p_vec, int pos) : _pos(pos), _p_vec(p_vec){}    // these three methods form the basis of an iterator for use with a range-based for loop    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;    const Iter& operator++()    {        ++_pos;        // although not strictly necessary for a range-based for loop        // following the normal convention of returning a value from        // operator++ is a good idea.        return *this;    }};class IntVector{private:    int _data[100];public:    IntVector(){}    int get(int col) const    {        return _data[col];    }    Iter begin() const    {        return Iter(this, 0);    }    Iter end() const    {        return Iter(this, 100);    }    void set(int index, int val)    {        _data[index] = val;    }};int Iter::operator*() const{    return _p_vec->get(_pos);}// sample usage of the range-based for loop on IntVectorint main(){    IntVector v;    for(int i = 0; i < 100; i++)    {        v.set(i,i);    }    for( int i : v)    {        cout << i << endl;    }}

这段代码需要注意的是,它不允许在for循环中使用引用&,而去实现IntVector元素的修改。这很容易实现,改变get()的返回值为一个引用,但是这样做,会使代码变长,我们这里只是关注基本结构。

4 基于范围的循环增加性能吗?

用GCC4.6版本编译器测试,发现基于范围的for循环并没有比正常的STL迭代器有性能方面的提升,但是似乎跟STL的for_each函数对性能的提升是一样的,for_each函数使用了和迭代器相同的迭代模型。

5 编译器的支持度

不幸的是,基于范围的循环没有被很好滴支持。GCC4.6版本以上。

0 0
原创粉丝点击