【问题标题】:Code for a basic random access iterator based on pointers?基于指针的基本随机访问迭代器的代码?
【发布时间】:2012-08-19 00:24:53
【问题描述】:

我从未实现过类似 STL 的迭代器,我试图了解如何实现基于指针的非常基本的东西。一旦我有了这门课,我就可以修改它来做更复杂的事情。因此,这是第一步,我需要它坚如磐石才能理解如何编写我自己的迭代器(无需提升)。

我已经编写了以下代码,并且我知道其中有错误。你能帮我正确设计一个受此启发的随机访问迭代器类吗:

template<Type> class Container<Type>::Iterator : public std::iterator<random_access_iterator_tag, Type>
{
    // Lifecycle:
    public:
        Iterator() : _ptr(nullptr) {;}
        Iterator(Type* rhs) : _ptr(rhs) {;}
        Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {;}

    // Operators : misc
    public:
        inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;}
        inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;}
        inline Iterator& operator+=(const int& rhs) {_ptr += rhs; return *this;}
        inline Iterator& operator-=(const int& rhs) {_ptr -= rhs; return *this;}
        inline Type& operator*() {return *_ptr;}
        inline Type* operator->() {return _ptr;}
        inline Type& operator[](const int& rhs) {return _ptr[rhs];}

    // Operators : arithmetic
    public:
        inline Iterator& operator++() {++_ptr; return *this;}
        inline Iterator& operator--() {--_ptr; return *this;}
        inline Iterator& operator++(int) {Iterator tmp(*this); ++_ptr; return tmp;}
        inline Iterator& operator--(int) {Iterator tmp(*this); --_ptr; return tmp;}
        inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);}
        inline Iterator operator-(const Iterator& rhs) {return Iterator(_ptr-rhs.ptr);}
        inline Iterator operator+(const int& rhs) {return Iterator(_ptr+rhs);}
        inline Iterator operator-(const int& rhs) {return Iterator(_ptr-rhs);}
        friend inline Iterator operator+(const int& lhs, const Iterator& rhs) {return Iterator(lhs+_ptr);}
        friend inline Iterator operator-(const int& lhs, const Iterator& rhs) {return Iterator(lhs-_ptr);}

    // Operators : comparison
    public:
        inline bool operator==(const Iterator& rhs) {return _ptr == rhs._ptr;}
        inline bool operator!=(const Iterator& rhs) {return _ptr != rhs._ptr;}
        inline bool operator>(const Iterator& rhs) {return _ptr > rhs._ptr;}
        inline bool operator<(const Iterator& rhs) {return _ptr < rhs._ptr;}
        inline bool operator>=(const Iterator& rhs) {return _ptr >= rhs._ptr;}
        inline bool operator<=(const Iterator& rhs) {return _ptr <= rhs._ptr;}

    // Data members
    protected:
        Type* _ptr;
};

非常感谢。

【问题讨论】:

  • 什么错误?编译器错误?链接器错误?运行时错误?逻辑错误?还有什么?
  • “我知道有错误”——这是某种测试吗?我不认为 SO 是合适的网站...
  • 指针是一个迭代器。用类包装它的目的是什么?
  • 目的是了解如何正确实现一个迭代器类(特别是函数签名和函数的作用)。
  • 嗯,你并不需要到处都是public,但由于你没有数据成员,所以没有区别。 return Iterator(_ptr+rhs); 理论上会产生额外的不必要的临时性,您可以只使用return _ptr+rhs;。

标签: c++ stl iterator


【解决方案1】:

您的代码存在以下问题:

  • 您没有遵循三/五规则。在您的情况下,最好的选择是不要声明任何自定义析构函数、复制/移动构造函数或复制/移动赋值运算符。让我们遵循所谓的零规则。
  • Iterator(Type* rhs) 可以是私有的,Container 可以标记为Iterator 的朋友,但这不是绝对必要的。
  • operator=(Type* rhs) 是个坏主意。这不是类型安全的意义所在。
  • post-in(de)crementation 应该返回Iterator,而不是Iterator &amp;。
  • 添加两个迭代器没有任何意义。
  • 减去两个迭代器应该返回一个差异,而不是一个新的迭代器。
  • 您应该使用std::iterator&lt;std::random_access_iterator_tag, Type&gt;::difference_type 而不是const int &amp;。
  • 如果方法不修改对象,则应标记为const。

有用资源:RandomAccessIterator @ cppreference.com

这是您的代码的固定版本:

template<typename Type>
class Container<Type>::Iterator : public std::iterator<std::random_access_iterator_tag, Type>
{
public:
    using difference_type = typename std::iterator<std::random_access_iterator_tag, Type>::difference_type;
    
    Iterator() : _ptr(nullptr) {}
    Iterator(Type* rhs) : _ptr(rhs) {}
    Iterator(const Iterator &rhs) : _ptr(rhs._ptr) {}
    /* inline Iterator& operator=(Type* rhs) {_ptr = rhs; return *this;} */
    /* inline Iterator& operator=(const Iterator &rhs) {_ptr = rhs._ptr; return *this;} */
    inline Iterator& operator+=(difference_type rhs) {_ptr += rhs; return *this;}
    inline Iterator& operator-=(difference_type rhs) {_ptr -= rhs; return *this;}
    inline Type& operator*() const {return *_ptr;}
    inline Type* operator->() const {return _ptr;}
    inline Type& operator[](difference_type rhs) const {return _ptr[rhs];}
    
    inline Iterator& operator++() {++_ptr; return *this;}
    inline Iterator& operator--() {--_ptr; return *this;}
    inline Iterator operator++(int) const {Iterator tmp(*this); ++_ptr; return tmp;}
    inline Iterator operator--(int) const {Iterator tmp(*this); --_ptr; return tmp;}
    /* inline Iterator operator+(const Iterator& rhs) {return Iterator(_ptr+rhs.ptr);} */
    inline difference_type operator-(const Iterator& rhs) const {return _ptr-rhs.ptr;}
    inline Iterator operator+(difference_type rhs) const {return Iterator(_ptr+rhs);}
    inline Iterator operator-(difference_type rhs) const {return Iterator(_ptr-rhs);}
    friend inline Iterator operator+(difference_type lhs, const Iterator& rhs) {return Iterator(lhs+rhs._ptr);}
    friend inline Iterator operator-(difference_type lhs, const Iterator& rhs) {return Iterator(lhs-rhs._ptr);}
    
    inline bool operator==(const Iterator& rhs) const {return _ptr == rhs._ptr;}
    inline bool operator!=(const Iterator& rhs) const {return _ptr != rhs._ptr;}
    inline bool operator>(const Iterator& rhs) const {return _ptr > rhs._ptr;}
    inline bool operator<(const Iterator& rhs) const {return _ptr < rhs._ptr;}
    inline bool operator>=(const Iterator& rhs) const {return _ptr >= rhs._ptr;}
    inline bool operator<=(const Iterator& rhs) const {return _ptr <= rhs._ptr;}
private:
    Type* _ptr;
};
  

【讨论】:

  • Iterator operator++(int) const - 不能是 const
【解决方案2】:

总的来说,您的方法是正确的。 postfix increment/decrement operator should return by value,不作为参考。我也有疑问:

Iterator(Type* rhs) : _ptr(rhs) {;}

这告诉大家这个迭代器类是围绕指针实现的。我会尝试使此方法只能由容器调用。分配给指针也是如此。 添加两个迭代器对我来说毫无意义(我会留下“iterator+int”)。减去两个指向同一个容器的迭代器可能会有意义。

【讨论】:

  • 正如他所说,这是一项教育活动,这就是他全力以赴的原因。我也对operator[] 感到惊讶,但它是用于随机访问迭代器的! en.cppreference.com/w/cpp/concept/RandomAccessIterator
  • 我相信你需要inline difference_type operator-(const Iterator&amp;) 而不是inline Iterator operator-(const Iterator&amp;)。我不相信你对operator+ 也需要同样的东西。如果没有difference_type operator-,某些算法(如std::sort)似乎无法工作。您不能同时拥有两者,因为只有返回类型不同。
【解决方案3】:

看看 Boost 是如何做到的,boost/container/vector.hpp - vector_const_iterator 和 vector_iterator 中的迭代器相当容易理解基于指针的迭代器。

【讨论】:

    猜你喜欢
    • 2019-12-06
    • 2021-03-02
    • 2020-04-23
    • 1970-01-01
    • 2022-11-14
    • 2021-11-17
    • 1970-01-01
    • 2011-05-17
    • 2017-09-02
    相关资源
    最近更新 更多