【问题标题】:What is the difference between STL containers iterator and C pointer iteratorSTL容器迭代器和C指针迭代器有什么区别
【发布时间】:2014-12-05 05:50:26
【问题描述】:

我正在编写一个反向迭代器作为我自己的自定义向量类的一部分。到目前为止,我写的内容如下。

class MyVector
{
  public:

  typedef T                           value_type;
  typedef value_type*                 pointer;
  typedef const value_type*           const_pointer;
  typedef value_type&                 reference;
  typedef const value_type&           const_reference;
  typedef pointer                     iterator;
  typedef const_pointer               const_iterator;
  typedef size_t                      size_type;

    class reverse_iterator
    {
        private:

        iterator iter;

        public:

        inline reverse_iterator(iterator a=0) : iter(a) {}
        inline reverse_iterator(const reverse_iterator& rev_iter) : iter(rev_iter.iter) {}
        inline reverse_iterator& operator++()
        {
            --iter;
            return *this;
        }
        // and remaining other operator functions
    };

  inline iterator begin (void) { return ((iterator)data_array);           }
  inline iterator end (void)   { return ((iterator)data_array+number_of_elements); }
  inline reverse_iterator      rbegin(void)    { return end()-1;}
  inline reverse_iterator      rend(void)      { return begin()-1;}


    //functions for myvector class 
}; //end of Myvector class

在上面的类迭代器只是C风格的指针,reverse_iterator是类。所以当我这样做时

    main()
    {
        myVector<int> i;
        myVector<int>::reverse_iterator rit= i.begin();
    }

我的 reverse_iterator 使用 begin() 函数初始化,代码正在编译和运行。但这不会发生在 STL 的迭代器和 reverse_iterator 的情况下。它们阻止了这种初始化。例如reverse_iterator 不允许自己用 begin() 函数初始化,它必须用 rbegin() 初始化。

那么我应该怎么做才能避免这种初始化?我应该写一个不同的迭代器,就像在 STL 中一样。而且我认为不可能写出来..请给我一些解决方案...

【问题讨论】:

  • 您明确允许将iterator 转换为reverse_iterator,因为您已经为后者提供了从前者转换的构造函数。删除该构造函数。
  • 如果您将代码示例简化为MCVE,会更容易。很多代码与问题无关,但编译不够。

标签: c++ stl iterator containers


【解决方案1】:

迭代器和反向迭代器有一些区别。

最明显的:递增每个迭代器会使它们朝相反的方向移动。

不太明显:begin() 的返回不是反向迭代器的结束。 begin()-1 会。请记住,end() 代表“过去的结束”,因为 C++ 范围是半开的,即 [开始,结束)。如果您只是在反向迭代器中交换 begin()end(),那么反向迭代器将具有范围(开始,结束)。

换句话说,STL 容器同时具有begin()end()rbegin()rend() 是有原因的,即使迭代器和反向迭代器本身在某些方面可能是兼容的。

【讨论】:

    【解决方案2】:

    为了完全防止从iterator(指针)到reverse_iterator的转换,将reverse_iterator的构造函数设为私有,并将MyVector设为reverse_iterator的朋友:

    class MyVector
    {
      // ...
      class reverse_iterator
      {
      private:
        friend class MyVector;
        reverse_iterator(iterator a=0) : iter(a) {}
        // ...
      };
      // ...
    };
    

    如果您希望该转换可用,但不是自动的,则只需创建相应的构造函数explicit

    class MyVector
    {
      // ...
      class reverse_iterator
      {
      public:
        explicit reverse_iterator(iterator a=0) : iter(a) {}
        // ...
      };
      // ...
    };
    

    在不相关的注释中,我还注意到您对 rbegin() 的实现可能会调用未定义的行为(我无法确定,因为它取决于初始化 data_array 的代码):您不允许递减指针到数组的开头。

    顺便说一句,在您的情况下,关键字inline 不是必需的;如果在类定义中编写成员函数体,它会自动内联。当然,inline 也无妨。

    【讨论】:

      猜你喜欢
      • 2015-09-16
      • 2012-01-28
      • 2013-04-16
      • 2010-11-04
      • 2011-02-13
      • 2012-02-10
      • 1970-01-01
      • 2010-10-27
      • 1970-01-01
      相关资源
      最近更新 更多