繁体   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