跳轉到內容

更多 C++ 習語/迭代器對

來自 Wikibooks,開放的書籍,開放的世界

迭代器對

[編輯 | 編輯原始碼]

指定一個數據值的範圍,而無需擔心用於資料值的底層資料結構。

也稱為

[編輯 | 編輯原始碼]

有時這被稱為迭代器範圍。

眾所周知,使用複製建構函式從另一個 vector<int> 建立 vector<int> 是很有用的。類似地,使用應用於成員模板建構函式的 透過成員模板強制轉換 習語,從 vector<int> 建立 vector<double> 是很有用的。下面給出了一個程式碼示例。

template <class T>
class vector
{
  public:
    vector (const vector<T> &); // copy constructor
    template <class U>
    vector (const vector<U> &); // constructor using Coercion by Member Template Idiom.
};

vector 介面對於某些需求來說仍然不夠靈活。例如,vector 無法從列表或集合或 POD 陣列建立自身。

template <class T>
class vector
{
  public:
    vector (const list<T> &); 
    // constructor must know the interface of list<T> (not necessarily std::list)
    vector (const set<T> &); 
    // constructor must know the interface of set<T> (not necessarily std::set)
    vector (const T * pod_array);
    // another constructor - does not know where pod_array ends - too inflexible!
};

迭代器對是一種解決此挑戰的習語。它基於迭代器設計模式(顯然!)。迭代器模式的意圖:提供一個遍歷某些聚合結構的物件,抽象出對該結構實現的假設。

解決方案和示例程式碼

[編輯 | 編輯原始碼]

一對迭代器用於指定一個值的範圍的開始和結束。憑藉迭代器設計模式,無論是誰(在我們的示例向量中)使用迭代器對習語,都可以訪問範圍而無需擔心聚合資料結構的實現。唯一的要求是迭代器應該公開一個固定的、最小的介面,例如前增量運算子。

template <class T>
class vector
{
    T * mem;
  public:
    template <class InputIterator>
    vector (InputIterator begin, InputIterator end) // Iterator-pair constructor
    {
      // allocate enough memory and store in mem.
      mem=new T[std::distance(begin, end)];
      for (int i = 0; begin != end; ++i)
      {
        mem[i] = *begin;
        ++begin;
      }
    }
};
int main (void)
{
  std::list<int> l(4);
  std::fill(l.begin(),l.end(), 10);    // fill up list using iterator pair technique.
  std::set<int> s(4);
  std::fill(s.begin(),s.end(), 20);    // fill up set using iterator pair technique.

  std::vector<int> v1(l.begin(), l.end());  // create vector using iterator pair technique.
  std::vector<int> v2(s.begin(), s.end());  // create another vector.
}

迭代器對習語通常與成員模板結合使用,因為迭代器的確切型別不是先驗知道的。它可以是 set<T>::iterator 或 list<T>::iterator 或 POD 陣列。無論型別如何,以迭代器對錶示的任何通用演算法都可以工作。通常使用說明迭代器型別應該建模的概念很有用。在上面的示例中,迭代器至少需要建模 InputIterator 概念。有關迭代器類別(標籤)及其用法的更多資訊,請參見標籤分派習語。

有時迭代器對習語是不可避免的。例如,要從帶有嵌入空字元的字元緩衝區構造一個 std::string,迭代器對習語是不可避免的。

char buf[] = { 'A', 'B', 0, 'C', 0, 'D'};
std::string str1 (buf); // only creates "AB"
std::string str2 (buf, buf + sizeof (buf) / sizeof (*buf)); // Using iterator pair. Creates "AB_C_D"
// buf is start of the range and buf + sizeof (buf) / sizeof (*buf) is the end of the range.

std::cout << str1 << " length = " << str1.length() << std::endl; // AB length = 2
std::cout << str2 << " length = " << str2.length() << std::endl; // AB_C_D length = 6

已知用途

[編輯 | 編輯原始碼]

所有標準容器

[編輯 | 編輯原始碼]
華夏公益教科書