概况
CPP foreach循环是CPP11引入的新特性,其能够很轻易地完成对可迭代对象的遍历,一般而言,一个典型的foreach循环结构如下:
1 2 3
| for (const auto &item : contain) { do_something(item); }
|
可迭代对象
可迭代对象(上述示例中的contain)是一个可以使用迭代器遍历的对象,其要求满足以下条件:
实现了begin方法,并要求该方法返回一个迭代器且无参数,一个典型的声明如下:
iterator begin() const;
实现了end方法,并要求该方法返回一个迭代器且无参数,一个典型的声明如下:
iterator end() const;
而迭代器要求满足以下条件:
实现了相应的构造函数和赋值函数。
实现了operator++方法,一个典型的声明如下:
iterator &operator++();
实现了operator!=方法,一个典型的声明如下:
bool operator!=(const iterator &) const;
实现了operator*方法,一个典型的声明如下:
T &operator*() const;
等价代码
实际上CPP中的foreach循环是一种语法糖,其等价于如下代码:
1 2 3 4 5 6 7 8
| { iterator first = contain.begin(); iterator last = contain.end(); while (first != last) { do_something(*first); ++first; } }
|
代码示例
下面展示了一个对自定义可迭代对象进行迭代的Demo示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <iostream>
class Range { public: class RangeIterator { public: explicit RangeIterator(std::size_t i) :m_number_(i) { std::cout << __FILE__ << ':' << __LINE__ << " ictor" << std::endl; }
RangeIterator(const RangeIterator &it) :RangeIterator(it.m_number_) { std::cout << __FILE__ << ':' << __LINE__ << " icopy_ctor" << std::endl; }
RangeIterator(RangeIterator &&it) :RangeIterator(it.m_number_) { std::cout << __FILE__ << ':' << __LINE__ << " imove_ctor" << std::endl; }
RangeIterator &operator=(const RangeIterator &it) { m_number_ = it.m_number_; std::cout << __FILE__ << ':' << __LINE__ << " icopy" << std::endl; return *this; }
RangeIterator &operator=(RangeIterator &&it) { m_number_ = it.m_number_; std::cout << __FILE__ << ':' << __LINE__ << " imove" << std::endl; return *this; }
bool operator!=(const RangeIterator &rit) const { std::cout << __FILE__ << ':' << __LINE__ << " operator!=" << std::endl; return m_number_ != rit.m_number_; }
RangeIterator &operator++() { std::cout << __FILE__ << ':' << __LINE__ << " operator++" << std::endl; ++m_number_; return *this; }
std::size_t operator*() const { std::cout << __FILE__ << ':' << __LINE__ << " *" << std::endl; return m_number_; } private: std::size_t m_number_; }; public: explicit Range(std::size_t first = 0, std::size_t last = SIZE_MAX) : m_first_(first), m_last_(last) { std::cout << __FILE__ << ':' << __LINE__ << " ctor" << std::endl; }
Range(const Range &range) : m_first_(range.m_first_), m_last_(range.m_last_) { std::cout << __FILE__ << ':' << __LINE__ << " copy_ctor" << std::endl; }
Range(Range &&range) : m_first_(std::move(range.m_first_)), m_last_(std::move(range.m_last_)) { std::cout << __FILE__ << ':' << __LINE__ << " move_ctor" << std::endl; }
Range &operator=(const Range &range) { m_first_ = range.m_first_; m_last_ = range.m_last_; std::cout << __FILE__ << ':' << __LINE__ << " copy" << std::endl; return *this; }
Range &operator=(Range &&range) { m_first_ = std::move(range.m_first_); m_last_ = std::move(range.m_last_); std::cout << __FILE__ << ':' << __LINE__ << " move_ctor" << std::endl; return *this; }
RangeIterator begin() const { std::cout << __FILE__ << ':' << __LINE__ << " begin" << std::endl; return m_first_; }
RangeIterator end() const { std::cout << __FILE__ << ':' << __LINE__ << " end" << std::endl; return m_last_; } private: RangeIterator m_first_; RangeIterator m_last_; };
int main() { for (const auto &i : Range(0, 4)) { std::cout << __FILE__ << ':' << __LINE__ << ' ' << i << std::endl; } return 0; }
|
编译运行后的结果为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| test0.cpp:8 ictor test0.cpp:8 ictor test0.cpp:52 ctor test0.cpp:80 begin test0.cpp:8 ictor test0.cpp:12 icopy_ctor test0.cpp:85 end test0.cpp:8 ictor test0.cpp:12 icopy_ctor test0.cpp:32 operator!= test0.cpp:43 * test0.cpp:95 0 test0.cpp:37 operator++ test0.cpp:32 operator!= test0.cpp:43 * test0.cpp:95 1 test0.cpp:37 operator++ test0.cpp:32 operator!= test0.cpp:43 * test0.cpp:95 2 test0.cpp:37 operator++ test0.cpp:32 operator!= test0.cpp:43 * test0.cpp:95 3 test0.cpp:37 operator++ test0.cpp:32 operator!=
|