• C++11系列-区间迭代


    C++11系列-区间迭代

    2013-08-20

    在我前面介绍C++11的文章中,我提到C++11将会带来一些实用的改进。我的意思是它将移除一些不必要的打字和其它影响快速编码的壁垒。我前面讲过的auto关键字就是一个例子;现在我想讲一下区间迭代(range-based for loop)。

    区间迭代的基本语法

    近来,基本上所有现代编程语言都有一种对一个区间写for循环的便捷方式。最终,C++也有了相同的概念;你可以给循环提供一个容器,它帮你迭代。前面我们已经在什么是C++11中看到了一些简单的例子。让我们回忆一下区间迭代的样子:

    1. vector<int> vec;
    2. vec.push_back( 10 );
    3. vec.push_back( 20 );
    4. for (int i : vec )
    5. {
    6. cout << i;
    7. }

    上面代码打印一个名叫vec的vector的内容,用i去捕获vector里面的值,直至vector的最后。你也可以用auto代替类型便利的迭代复杂的数据结构。例如,迭代一个map:

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

    修改vector的值

    假如你想修改你正在迭代的容器的值,或者你想避免拷贝大对象,你可以用引用的变量遍历。比如,下面的迭代对一个整形vector中每个元素的值加1。

    1. vector<int> vec;
    2. vec.push_back( 1 );
    3. vec.push_back( 2 );
    4. for (int& i : vec )
    5. {
    6. i++; // increments the value in the vector
    7. }
    8. for (int i : vec )
    9. {
    10. // show that the values are updated
    11. cout << i << endl;
    12. }

    区间意味着什么?

    Strings,arrays,和所有的STL容器可以被新的区间迭代方式迭代。但是如果你想让你自己的数据结构使用这个新语法怎么办?

    为了使这个数据结构可迭代,它必须类似于STL迭代器。

    • 这个数据结构必须要有begin和end方法,成员方法和独立函数都行,这两个方法分别返回开始和结束的迭代器
    • 迭代器支持*操作符、!=操作符、++方法(前缀形式,成员函数和独立函数都行)

    就这些!实现这五个函数,你就可以有一个支持区间迭代的数据结构。因为begin、end可以是非成员函数,你甚至可以适配现有数据结构而不用实现STL风格的迭代器。所有你要做的是创建你自己的支持*、前缀++和!=的迭代器,并且定义好自己的begin、end。

    区间迭代如此NICE。所以我怀疑大部分还不支持STL迭代模型的容器都会想添加某种适配方式以支持区间迭代。这里有一个小程序演示创建一个支持区间迭代的迭代器。这个例子里,我创建了一个固定Size是100的IntVector,并且可以被一个叫做Iter的类迭代。

    1. #include <iostream>
    2. using namespace std;
    3. class IntVector;
    4. class Iter
    5. {
    6. public:
    7. Iter (const IntVector* p_vec, int pos)
    8. : _pos( pos )
    9. , _p_vec( p_vec )
    10. { }
    11. // 这三个方法组成支持区间迭代的迭代器的基础
    12. bool
    13. operator!= (const Iter& other) const
    14. {
    15. return _pos != other._pos;
    16. }
    17. int operator* () const;
    18. const Iter& operator++ ()
    19. {
    20. ++_pos;
    21. return *this;
    22. }
    23. private:
    24. int _pos;
    25. const IntVector *_p_vec;
    26. };
    27. class IntVector
    28. {
    29. public:
    30. IntVector ()
    31. {
    32. }
    33. int get (int col) const
    34. {
    35. return _data[ col ];
    36. }
    37. Iter begin () const
    38. {
    39. return Iter( this, 0 );
    40. }
    41. Iter end () const
    42. {
    43. return Iter( this, 100 );
    44. }
    45. void set (int index, int val)
    46. {
    47. _data[ index ] = val;
    48. }
    49. private:
    50. int _data[ 100 ];
    51. };
    52. int
    53. Iter::operator* () const
    54. {
    55. return _p_vec->get( _pos );
    56. }
    57. int main()
    58. {
    59. IntVector v;
    60. for ( int i = 0; i < 100; i++ )
    61. {
    62. v.set( i , i );
    63. }
    64. for ( int i : v ) { cout << i << endl; }
    65. }

    注意这段代码中区间迭代时,不允许以引用修改IntVector中的元素。这是为了不使代码变长而影响代码的主要结构,所以并没添加返回引用类型的函数。

    区间迭代提升性能?

    在我使用GCC4.6的有限的测试中,我并没看到区间迭代相对于标准STL迭代的性能提升,但好像可以和STL中的for_each拥有同样的性能。

    编译器支持

    不幸的是,区间迭代的编译器支持的不好。MSVC11以后开始支持,GCC是4.6以后支持。


    转自:http://towriting.com/blog/2013/08/20/ranged-for-loop/

    无欲则刚 关心则乱
  • 相关阅读:
    runloop源代码
    runloop的source
    How an Event Enters a Cocoa Application
    RunLoop主要处理以下6类事件
    NSRunloop总结
    performSelector与objc_msgSend
    iOSUI显示思想
    NSPort与NSRunloop的关系是流与消息调度的关系
    Core Animation 负责将bitmap绑定提交到 GPU-[CALayer _display]
    iOS构建流畅的交互界面--CPU,GPU资源消耗的原因和解决方案
  • 原文地址:https://www.cnblogs.com/xjyxp/p/11453236.html
Copyright © 2020-2023  润新知