1. 程式人生 > >C++筆記------叠代器

C++筆記------叠代器

c++筆記 cast typedef 讀取 只讀 可能 ring fis void

STL是一種泛型編程。對象編程關註的是編程的數據方面,泛型編程關註的是算法的通用,它們之間的共同點的抽象和創建可重用代碼,但理念不同。

STL使用術語“概念”描述叠代器所需要滿足的一系列要求,如正向叠代器是一種要求,而不是類型。

STL使用術語“改進”來表示這種概念上的繼承,概念具有類似繼承的關系,但不能將C++繼承機制用於叠代器。

概念的具體實現被稱為模型,所以一個指向int的常規指針是一個隨機訪問叠代器的模型,也是一個正向叠代器的模型。

STL首先為每個容器類定義了相應的叠代器類型,叠代器可以是指針,也可以是對象。叠代器都將提供一些基礎操作,如*和++。

  其次每個容器類都有超尾標記,通過讓叠代器++操作,從第一個元素逐步指向超尾位置,實行遍歷容器中每一個元素。

STL定義了5種叠代器,分別為輸入叠代器輸出叠代器正向叠代器雙向叠代器隨機訪問叠代器。這5種叠代器都可以執行解除應用操作,如果兩個叠代器相同,則對它們執行解除引用得到的值也一樣。叠代器的特征和容器的特征是基於算法要求進行設計。

  1.輸入叠代器:

  (1)“輸入”是指從容器中獲取信息,所以輸入叠代器用來讀取容器中信息,但不能讓程序修改值。

  (2)輸入叠代器是單向的,可以使用++運算符進行遞增操作,但不能倒退。

  2.輸出叠代器:

  (1)“輸出”是指信息從程序中傳輸給容器,所以只能讓程序修改容器的值,但不能讀取。

  (2)輸出叠代器也是單向的,可以使用++運算符進行遞增操作,但不能倒退。

Ps:對於單通行,只寫的算法,可以使用輸出叠代器;對於單通行,只讀的算法,可以使用輸入叠代器。

  3.正向叠代器:

  (1)正向叠代器只使用++運算符來遍歷容器,能按相同的順序進行遍歷。

  (2)正向叠代器遞增後,仍可以對前面的叠代器(已經保存的)值進行解除引用操作,可以得到相同的值。

  (3)正向叠代器既可以讀取和修改數據,也可以只讀數據。

  4.雙向叠代器:

  (1)包含所有正向叠代器的特性,支持遞減運算符(a--和--a)。

  5.隨機叠代器:

  (1)能夠直接跳到容器中任何一個元素,進行隨機訪問,包含了所有雙向叠代器的特性。

Ps:

  1.編寫算法時,通過使用最低級別的叠代器,可以增加算法的通用性。例如fing()函數可以用於任何包含可讀取的叠代器的容器。而sort()函數需要隨機訪問叠代器,所以只有支持這種叠代器的容器。

  2.各種叠代器的類型並不是確定的,只是一種概念性描述。每個容器類定義一個類級的typedef 名稱-----iterator。

如前所說,叠代器是廣義指針,而指針滿足叠代器所有要求,因此STL算法可以使用對基於指針的非STL容器進行操作。

例如:  

  C++將超尾概念用於數組,可以將STL的算法用於常規數組。指針也是叠代器,也使得STL算法用於常規數組。

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

void output(const int s) { cout << s << " "; }

int main()
{
    int casts[10] = { 6,7,2,9,4,11,8,7,10,5 };
    std::vector<int> dice(10);
    //將數據從一種容器復制到另一種容器 
    //前兩個參數復制範圍,最後一個參數復制到什麽位置。 
    //目標容器必須足夠大,以便能容納元素 
    copy(casts, casts + 10, dice.begin());
    for (auto x : casts) cout << x << " ";//基於範圍的for循環 
    cout << endl;
    ostream_iterator<int, char>out_iter(cout, " ");
                                          //適配器——一個類或函數,可以將其它接口轉換成STL使用的接口
                                          //第一個參數:指出發送給輸出流的數據類型
                                          //第二個參數:指出輸出流使用的字符類型(可能是wchar_t)
                                          //構造函數的第一個參數:指出使用的輸出流
                                          //第二個參數:輸出流的每個數據項後面顯示的分隔符 
    copy(dice.begin(), dice.end(), out_iter);
    cout << endl;
    *out_iter++ = 15; //將15和空格組成的字符串發送到cout管理的輸出流中    想當於 cout << 15 << " "; 
    cout << endl;
    //可以直接使用,而不創建命名叠代器 
    copy(dice.begin(), dice.end(), ostream_iterator<int, char>(cout, " "));
    std::vector<int> dice1(10);
    vector<int> ::iterator rp;
    for (rp = dice1.begin(); rp != dice1.end(); rp++)
        cin >> *rp;
    for_each(dice1.begin(), dice1.end(), output);
    cout << endl;
    vector<int>::reverse_iterator ri; //對 revere_iterator執行遞增操作會導致它自減 
                                      //rbegin() and end() 返回值一樣,但類型不一樣(reverse_iterator and iterator)
                                      //rend() and begin() 返回值一樣,類型不一樣,都返回指向第一元素的地址 
                                      //在對ri進行解除引用之前,先自減,在解除引用。例如:ri執行位置6,*ri是位置5的數值 
    for (ri = dice1.rbegin(); ri != dice1.rend(); ++ri)
        cout << *ri << " ";
    cout << endl;
    return 0;
}

Ps:

  1.為什麽ri需要先自減?

    因為rbegin()返回超尾,所以不能進行解除引用,同理rend()返回的是第一個元素地址,所以必須提早一個位置停止(區間的結尾不包括在區間內)。

除了以上已用叠代器,還有以下三種插入叠代器:

  back_insert_iterator:將元素插入容器尾部中

  front_insert_iterator:將元素插入容器前端

  insert_iterator:將元素插入指定的位置前面

以上三種叠代器可以提高STL算法通用性,可以將容器類型作為模版參數。例如:

  back_insert_iterator<vector<int> > back_iter(dice)

  insert_iterator<vector<int> > insert_iter(dice,dice.begin() );

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <string>

void output(const std::string &s) { std::cout << s << " "; }

using namespace std;
int main()
{
    string s1[4] = { "fine" , "fish","fashion","fate" };
    string s2[3] = { "I" , "am" , "Zhang" };
    string s3[2] = { "Zeze" , "good" };
    vector<string> words(4);
    copy(s1,s1 + 4,words.begin());
    for_each(words.begin(),words.end(),output);
    cout << endl;
    copy(s2,s2 + 2,front_insert_iterator<vector<string> >(words));
    for_each(words.begin(),words.end(),output);
    cout << endl;
    copy(s3,s3 + 2,insert_iterator<vector<string> >(words,words.begin()));
    for_each(words.begin(),words.end(),output);
    cout << endl;
    return 0;
}

C++筆記------叠代器