【C++】实现简单随机访问函数

RandomAccessIterator

【起因】

实现自定义线性表的题目中要求实现随机访问迭代器使可以调用 algorithms 库中的 sort 方法

【sort】

sort 函数中和 RandomAccessIterator 相关的只有形参类型 RandomIt[1], 因此只需考虑最简单的函数声明即可

template< class RandomIt >
void sort( RandomIt first, RandomIt last );
Type requirements

cppreference 中指出了与 RandomIt 相关的必要条件

由于第二条是限制 RandomIt 的解引用类型的(个人认为可以理解为容器中的元素的类型),因此这里不做讨论,以下的整理中也除去了和元素类型相关的部分。

graph LR; VS(ValueSwappable) --> LI(LegacyIterator); LI --> CC(CopyConstructible); LI --> CA(CopyAssignable); LI --> D(Destructible); LI --> l(lvaues is swappable, dereferenceable, incrementable); LI --> typedefs(has member typedefs: value_type, difference_type, reference, pointer, iterator_category);

以上是整理出的与 ValueSwappable 有关的 RandomIt 的内容,代码如下:

class iterator
{
public:
    // member typedefs
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef value_type &reference;
    typedef value_type *pointer;
    typedef std::random_access_iterator_tag iterator_category;

    // constructor
    iterator(pointer thePosition = 0) { position = thePosition; }
    // copy constructor, copy_constructible
    iterator(const iterator &it) = default;
    // copy_assignable, swappable
    iterator &operator=(const iterator &it)
    { position = it.position; return *this; }
    // destructible
    ~iterator() {}

    // dereferenceable
    reference operator[](int theIndex) const { return position[theIndex];}
    reference operator*() const { return *position; } // right value
    const pointer operator->() const { return position; }

    // incrementable
    iterator &operator++()
    { ++position; return *this; }
    iterator operator++(int)
    { iterator old = *this; ++position; return old; }

protected:
    pointer position;
}
expression return type
r += n It&
a + n
n + a
It
r -= n It&
i - n It
b - a difference_type
i[n] convertible to reference
a < b contextually convertible to bool
a > b contextually convertible to bool
a >= b contextually convertible to bool
a <= b contextually convertible to bool
--a It&
a-- convertible to const It&
i++ It
i != j contextually convertible to bool
*i reference, convertible to value_type
i->m
++r It&
a == b implicitly convertible to bool

以上是整理出的 LegacyRandomAccessIterator 包含的所有表达式(注意: LegacyRandomAccessIterator 与 ValueSwappable 中有其他交错的部分,这里不再提出),代码如下:

class iterator
{
    // +=
    iterator &operator+=(difference_type off)
    { position += off; return *this; }
    // a+n
    iterator operator+(difference_type off) const
    { return iterator(position + off); }
    // n+a
    friend iterator+(difference_type off, const iterator &it)
    { return iterator(it.position + off); }
    // -=
    iterator &operator-=(difference_type off)
    { position -= off; return *this; }
    // -
    iterator operator-(difference_type off) const
    { return iterator(position - off); }
    // -
    difference_type operator-(const iterator &it) const
    { return position - it.position; }
    // []
    reference operator[](int theIndex) const { return position[theIndex];}
    // <
    bool operator<(const iterator &it) const { return position < it.position; }
    // >
    bool operator>(const iterator &it) const { return position > it.position; }
    // <=
    bool operator<=(const iterator &it) const { return position <= it.position; }
    // >=
    bool operator>=(const iterator &it) const { return position >= it.position; }
    // a--
    iterator &operator--()
    { --position; return *this; }
    // --a
    iterator operator--(int)
    { iterator old = *this; --position; return old; }
    // ++a
    iterator &operator++()
    { ++position; return *this; }
    // a++
    iterator operator++(int)
    { iterator old = *this; ++position; return old; }
    // !=
    bool operator!=(const iterator &it) const { return position != it.position; }
    // *
    reference operator*() const { return *position; }
    // ->
    const pointer operator->() const { return position; }
    // ==
    bool operator==(const iterator &it) const { return position == it.position; }
}

【总结】

  1. 将以上两者组合,便完成了 RandomAccessIterator。
  2. RandomAccessIterator 是最复杂的迭代器。
graph LR; RandomAccessIterator --> LegacyBidirectionalIterator; LegacyBidirectionalIterator --> LegacyForwardIterator; LegacyForwardIterator --> LegacyOutputIterator; LegacyForwardIterator --> LegacyInputIterator;

【相关阅读】


【引申】

  • 如果线性表是数组实现的循环列表, iterator 该如何处理?
    1. 数组容量满时,begin() 和 end() 如何区分?
    2. 经过一系列操作之后,last 可能会到 first 之前,这时如何处理自增自减
提示

Iterator category for circular buffer
boost_circular_buffer_iterator


  1. 这点从 sort 的实现中不难看出,但从The above rules imply that LegacyRandomAccessIterator also implements LessThanComparable. 这句话来看, 形参类型 RandomIt 和 Compare 本身是有关系但是隐式的? ↩︎

  2. 如果你对为什么将其命名为 legacy 感兴趣,可以参考 New iterator requirements ↩︎

posted @ 2023-01-10 01:51  HelloEricy  阅读(85)  评论(0)    收藏  举报