C++中迭代器原理、失效和簡單實現

目錄

  1. 迭代器的使用
  2. 迭代器的種類
  3. 迭代器的失效
  4. 迭代器的實現

1.迭代器的使用

       爲了提升C++編程的效率,STL中提供了許多容器,包括vector、list、map、set等。有些容器例如vector能夠經過腳標索引的方式訪問容器裏面的數據,可是大部分的容器不能使用這種方式,例如list、map、set。STL中每種容器在實現的時候設計了一個內嵌的iterator類,不一樣的容器有本身專屬的迭代器,使用迭代器來訪問容器中的數據。除此以外,經過迭代器,能夠將容器和通用算法結合在一塊兒,只要給予算法不一樣的迭代器,就能夠對不一樣容器執行相同的操做,例如find查找函數。迭代器對指針的一些基本操做如*、->、++、==、!=、=進行了重載,使其具備了遍歷複雜數據結構的能力,其遍歷機制取決於所遍歷的數據結構,全部迭代的使用和指針的使用很是類似。經過begin,end函數獲取容器的頭部和尾部迭代器,end 迭代器不包含在容器以內,當begin和end返回的迭代器相同時表示容器爲空。ios

template<typename InputIterator, typename T>
InputIterator find(InputIterator first, InputIterator last, const T &value)
{
    while (first != last && *frist != value)
        ++first;
    return first;
}
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

int main(int argc, const char *argv[])
{
    int arr[5] = { 1, 2, 3, 4, 5};

    vector<int> iVec(arr, arr + 5);//定義容器vector
    list<int> iList(arr, arr + 5);//定義容器list

    //在容器iVec的頭部和尾部之間尋找整形數3
    vector<int>::iterator iter1 = find(iVec.begin(), iVec.end(), 3);
    if (iter1 == iVec.end())
        cout<<"3 not found"<<endl;
    else
        cout<<"3 found"<<endl;

    //在容器iList的頭部和尾部之間尋找整形數4
    list<int>::iterator iter2 = find(iList.begin(), iList.end(), 4);
    if (iter2 == iList.end())
        cout<<"4 not found"<<endl;
    else
        cout<<"4 found"<<endl;

    return 0;
}

2.迭代器的種類

根據迭代器所支持的操做,能夠把迭代器分爲5類。算法

1)   輸入迭代器:是隻讀迭代器,在每一個被遍歷的位置上只能讀取一次。例如上面find函數參數就是輸入迭代器。編程

2)   輸出迭代器:是隻寫迭代器,在每一個被遍歷的位置上只能被寫一次。數據結構

3)   前向迭代器:兼具輸入和輸出迭代器的能力,可是它能夠對同一個位置重複進行讀和寫。但它不支持operator--,因此只能向前移動。函數

4)   雙向迭代器:很像前向迭代器,只是它向後移動和向前移動一樣容易。this

5)   隨機訪問迭代器:有雙向迭代器的全部功能。並且,它還提供了「迭代器算術」,即在一步內能夠向前或向後跳躍任意位置,  包含指針的全部操做,可進行隨機訪問,隨意移動指定的步數。支持前面四種Iterator的全部操做,並另外支持it + n、it - n、it += n、 it -= n、it1 - it2和it[n]等操做。spa

STL每種容器類型都定義了 const_iterator,只能讀取容器的值,不能修改所指向容器範圍內元素的值。vector、string、Deque隨機存取迭代器;List、Set、map、mutiset、multimap雙向迭代器.net

3.迭代器失效

容器的插入insert和erase操做可能致使迭代器失效,對於erase操做不要使用操做以前的迭代器,由於erase的那個迭代器必定失效了,正確的作法是返回刪除操做時候的那個迭代器。設計

#include <vector>
using namespace std;

int main(int argc, const char *argv[]) {
    int arr[5] = { 1, 2, 3, 4, 5 };

    vector<int> iVec(arr, arr + 5); //定義容器vector
    //迭代器失效
//    for (vector<int>::iterator it = iVec.begin(); it != iVec.end();) {
//        iVec.erase(it);
//    }
    //返回erase操做以後的迭代器
    for (vector<int>::iterator it = iVec.begin();it != iVec.end();) {
        it = iVec.erase(it);
    }
    return 0;
}

4.迭代器的實現

STL中每一個容器都有本身的迭代器,各類迭代器的接口相同,內部實現卻不相同,這也直接體現了泛型編程的概念,下面在單鏈表類中內嵌入一個iterator的類來實現單鏈表的迭代3d

  1 #include <iostream>
  2 
  3 template<typename T>
  4 struct ListNode {
  5     T value;
  6     ListNode* next;
  7     ListNode() {
  8         next = 0;
  9     }
 10     ListNode(T val, ListNode *p = nullptr) :
 11             value(val), next(p) {
 12     }
 13 };
 14 
 15 template<typename T>
 16 class List {
 17 private:
 18     ListNode<T> *m_pHead;
 19     ListNode<T> *m_pTail;
 20     int m_nSize;
 21 public:
 22     List() {
 23         m_pHead = nullptr;
 24         m_pTail = nullptr;
 25         m_nSize = 0;
 26     }
 27     //從鏈表尾部插入元素
 28     void push_back(T value) {
 29         if (m_pHead == nullptr) {
 30             m_pHead = new ListNode<T>(value);
 31             m_pTail = m_pHead;
 32         } else {
 33             m_pTail->next = new ListNode<T>(value);
 34             m_pTail = m_pTail->next;
 35         }
 36 
 37     }
 38 
 39     //打印鏈表元素
 40     void print(std::ostream &os = std::cout) const {
 41         for (ListNode<T> *ptr = m_pHead; ptr != m_pTail->next ; ptr = ptr->next)
 42             std::cout << ptr->value << " ";
 43         os << std::endl;
 44     }
 45 
 46     //內置迭代器
 47     class iterator {
 48     private:
 49         ListNode<T> *m_ptr;
 50     public:
 51         iterator(ListNode<T>* p = nullptr) :
 52                 m_ptr(p) {
 53         }
 54 
 55         T operator*() const {
 56             return m_ptr->value;
 57         }
 58         ListNode<T>* operator->() const {
 59             return m_ptr;
 60         }
 61         iterator& operator++() {
 62             m_ptr = m_ptr->next;
 63             return *this;
 64         }
 65         iterator operator++(int) {
 66             ListNode<T>* tmp = m_ptr;
 67             m_ptr = m_ptr->next;
 68             return iterator(tmp);
 69         }
 70 
 71         bool operator==(const iterator &arg) const {
 72             return arg.m_ptr == this->m_ptr;
 73         }
 74 
 75         bool operator!=(const iterator &arg) const {
 76             return arg.m_ptr != this->m_ptr;
 77         }
 78 
 79     };
 80 
 81     //返回鏈表頭部指針
 82     iterator begin() const {
 83         return iterator(m_pHead);
 84     }
 85 
 86     //返回鏈表尾部指針
 87     iterator end() const {
 88         return iterator(m_pTail->next);
 89     }
 90 
 91     //其它成員函數
 92 
 93 };
 94 
 95 int main() {
 96     List<int> l;
 97     l.push_back(1);
 98     l.push_back(2);
 99     l.print();
100     for (List<int>::iterator it = l.begin(); it != l.end(); ++it) {
101         std::cout << *it << " ";
102     }
103     std::cout << std::endl;
104     return 0;
105 }

 

參考: http://blog.csdn.net/shudou/article/details/11099931

相關文章
相關標籤/搜索