自定義for循環

首先,這裏說的for循環,是指C++中新增的for(a : b)格式的for循環。
最近碰到了這樣的問題,就來記錄一下。如有錯漏,還望指摘。

C++新增的這種for循環,使用來遍歷容器中的每一個元素。但是有時候,我想自定義自己的容器,那能不能也使用這樣的for循環呢?
答案肯定是可以的。那麼需要什麼要求呢?

for循環的大致邏輯

要向弄明白有什麼需求,我們首先需要弄明白,這個for循環是怎麼實現的。
比如對於for(ele : list), 其實大致相當於如下代碼:

for(auto it = list.begin(); it != list.end(); ++it)
{
   ele = *it;
   // ......
}

自定義for循環要求

那麼我們就可以看出對於格式爲for(ele : list)的for循環語句,有如下要求

  1. 變量list對應的類型中必須包含begin()函數
  2. 變量list對應的類型中必須包含end()函數
  3. begin()函數的返回值類型中,必須實現了++操作符
  4. begin()函數的返回值類型中,必須實現了*操作符
  5. begin()函數的返回值類型中,必須實現了參數類型爲end()函數返回值類型的!=操作符。

實現

所以如下代碼就可以實現自定義for循環:

class ArrayEnd
{
public:
    int* ptr_;

    ArrayEnd(int* ptr) : ptr_(ptr) {}
};

class ArrayBegin
{
private:
    int* ptr_;
public:
    ArrayBegin(int* ptr) : ptr_(ptr) {}
    ArrayBegin& operator++()
    {
        ptr_++;
        return *this;
    }
    int& operator *() { return *ptr_; }
    bool operator != (const ArrayEnd& e) { return ptr_ != e.ptr_; }
};

class myArray
{
private:
    int* ptr_;
    int len_;
public:
    myArray(int* ptr, int len) : ptr_(ptr), len_(len) {}
    ArrayBegin begin() { return ArrayBegin(ptr_); }
    ArrayEnd end() { return ArrayEnd(ptr_ + len_); }
};

不過當然,一般我們會將ArrayBegin和ArrayEnd合併在一起成爲ArrayIterator:

class ArrayIterator
{
private:
    int* ptr_;
public:
    ArrayIterator(int* ptr) : ptr_(ptr) {}
    ArrayIterator& operator++()
    {
        ptr_++;
        return *this;
    }
    int& operator *() { return *ptr_; }
    bool operator != (const ArrayIterator& e) { return ptr_ != e.ptr_; }
};

class myArray
{
private:
    int* ptr_;
    int len_;
public:
    myArray(int* ptr, int len) : ptr_(ptr), len_(len) {}
    ArrayIterator begin() { return ArrayIterator(ptr_); }
    ArrayIterator end() { return ArrayIterator(ptr_ + len_); }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章