簡體   English   中英

創建自己的數據結構時,是否應該使用迭代器或索引來提供外部訪問?

[英]When creating my own data structure, should I use iterators or indices to provide access from the outside?

假設我正在用現代版本的C ++(例如11或14)編寫一個項目,並在該項目中使用STL。 在某個時刻,我需要對可以使用STL容器構建的特定數據結構進行編程。 DS封裝在一個類中(對嗎,將DS封裝在一個類中是在C ++中對其進行編碼的唯一正確方法嗎?),因此我需要提供某種接口來提供對該對象的讀和/或寫訪問。數據。 這就引出了一個問題:

我應該為此使用(1a)迭代器還是(1b)簡單的“索引”(即某種類型的數字)? 我現在正在使用的DS幾乎是線性的,但是當元素被刪除時,簡單的整數索引當然會失效。 那是我能想到的唯一反對這種方法的論點。

哪種方法更慣用? 支持和反對每一個的客觀技術論據是什么?

另外,當我選擇對自定義DS使用迭代器時,我應該(2a) public對內部使用的容器的迭代器進行typedef定義,還是(2b)從頭開始創建自己的迭代器? 在Boost等開放庫中,我看到了自定義迭代器是從頭開始編寫的。 另一方面,我覺得我還不能編寫適當的迭代器(即,與STL和/或Boost中的迭代器一樣詳細和復雜的迭代器)。

根據@πάνταῥεῖ請求編輯

在大學學習時,我在幾個項目中用幾個DS問了自己這個問題,但這是最后一次讓我來這里問問題的情況。

DS旨在表示三角形數組或頂點數組,或任何可能稱為三角形的數組。 點是,有兩個數組或列表,一個數組或列表存儲頂點坐標,另一個數組或列表存儲來自第一個數組的索引的三元組,因此代表三角形。 (這已經被編碼了數百億次,但是為了學習的目的,我想一次寫一次。)顯然,兩個數組應該保持同步,因此是封裝。 該組操作旨在包括使用同一數組中的頂點數據來添加(或也可以刪除)頂點,添加和刪除三角形(頂點三元組)。 我看到的是客戶端添加頂點,寫下索引/迭代器,然后發出調用以基於這些索引/迭代器添加三角形,這又將另一個索引/迭代器返回到生成的三角形。

哪種方法更慣用?

使用迭代器絕對是必經之路。 <algorithm>函數不適用於索引。 他們使用迭代器。 如果希望容器啟用以供<algorithm>的函數使用,則使用迭代器是唯一的方法。

通常,建議類提供自己的迭代器。 在后台,它可以是索引或STL迭代器(首選)。 但是,只要涉及外部客戶端和公共API,它們僅處理該類提供的迭代器。

例子1

  class Dictionary {
    private:
      typedef std::unordered_map<string, string> DictType;
    public:
      typedef DictType::iterator DictionaryIterator;
  };

例子2

  class Sequence {
    private:
      typedef std::vector<string> SeqType;
    public:
      struct SeqIterator {
        size_t index;
        SeqIterator operator++();
        string operator*();
      };
  };

如果客戶端僅在SeqIteratorSeqIterator ,則可以稍后將上述內容修改為

  class Sequence {
    private:
      typedef std::deque<string> SeqType;
    public:
      typedef SeqType::iterator SeqIterator;
  };

不會影響客戶。

我不明白為什么您不能同時獲得兩者,如果這對您的容器有意義。

std::vector具有迭代器和at / operator[]方法來提供索引訪問。

容器的API取決於您要向客戶端提供的操作。

  • 容器是否可迭代,即可以迭代每個元素? 然后,您應該提供一個迭代器。

  • 知道它們的地址,隨機訪問容器中的元素是否有意義? 然后,您還可以提供at(size_t) / operator[size_t]方法。

  • 知道一個特殊的“鍵”來隨機訪問容器中的元素是否有意義? 您可能應該提供at(key_type) / operator[key_type]方法。


至於您有關自定義迭代器或現有迭代器重用的問題:

如果您的容器基本上是為現有容器添加一些插入/移除邏輯的包裝器,那么我認為公開定義現有迭代器是可以的,因為自定義迭代器可能會遺漏現有迭代器的某些功能,可能包含錯誤以及不會在現有的迭代器上添加任何重要功能。

另一方面,如果您以非標准的方式進行迭代(例如,我實施了一次recursive_unordered_map ,該recursive_unordered_map在構造時接受了父級recursive_unordered_map ,並且會在其自身的unordered_map和其父級(以及其父級的父級... )。為此,我必須實現一個自定義迭代器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM