【问题标题】:Implementation(overloading) of -> operator-> 运算符的实现(重载)
【发布时间】:2013-11-22 14:01:58
【问题描述】:

我有哈希表,我用二维向量实现的

std::vector<std::vector<std::string> > htable;

另外,我在 myiterator 类中编写了 ++、- 和 * 运算符,这是我的哈希表的子类。

class myiterator{
    public:
        myiterator();
        myiterator(std::vector<std::vector<std::string> >& v, int ii, int jj) : 
            vec(v), i(ii), j(jj) {}
        std::string operator*(){
            return vec[i][j];
        }
        myiterator& operator++(){
            if(j==vec[i].size()-1){
                int start=0;
                while(vec[start].size()==0){
                    start++;
                }
                i=start;
                j=0;
            }
            else{
                j++;
            }
            return *this;
        }
        // myiterator operator++(int); // postfix operator
        myiterator& operator--(){
            if(j==0){
                int end=vec[i].size()-1;
                while(vec[end].size()==0){
                    end--;
                }
                i=end;
                j=vec[end].size()-1;
            }
            else{
                j--;
            }
            return *this;
        } // prefix operator
        // myiterator operator--(int); // postfix operator
        std::string* operator->();
    private:
        std::vector<std::vector<std::string> >& vec; // the vector we are iterating over
        int i; // the position in the vector (first dimension)
        int j; // the position in the vector (second dimension)
    };
    myiterator begin() {
        int start=0;
        while(htable[start].size()==0){
            start++;
        }
        return (myiterator(htable, start, 0));
    }
    myiterator end(){
        int end=htable.size()-1;
        while(htable[end].size()==0){
            end--;
        }
        return (myiterator(htable, end, htable[end].size()-1));
    }

问题是,我必须如何实现 -> 运算符?他是做什么的?我google了一下,没看懂。对不起,如果我的问题是nooby和基本的。提前致谢。

【问题讨论】:

    标签: c++ iterator operators


    【解决方案1】:

    目前看起来不错。我会说

        std::string* operator->(){
            return &vec[i][j];
        }
    

    关于 operator-> 的奇怪之处在于,在调用用户定义的 operator-> 之后,编译器将在返回的任何内容上再次调用 operator->。所以你的 operator-> 应该返回你想要访问的对象的地址。

    【讨论】:

    • 哦,这么简单?因此,这意味着对于 ++、--、* 和 -> 运算符,我不需要额外的运算符,例如 == 或 != 或后缀运算符或类似的东西?
    • 我认为你需要 operator== 和 operator!=,你经常需要测试一个迭代器是否等于另一个。后缀运算符非常容易编写,因此您不妨拥有它们。
    【解决方案2】:

    通常应用程序将使用运算符 -> 用于返回指向内部对象的指针的智能指针对象。见usage

    【讨论】:

      【解决方案3】:

      John 已经回答了您关于 operator-&gt; 的问题。我只是想评论operator++operator--。我会发表评论,但这会有点长:)

      让我们从这里开始:

          myiterator& operator++(){
              if(j==vec[i].size()-1){
                  int start=0;
                  while(vec[start].size()==0){
                      start++;
                  }
                  i=start;
                  j=0;
              }
              else{
                  j++;
              }
              return *this;
          }
      

      你有start=0这一行。这意味着每次到达内部向量 (j==vec[i].size()-1) 的末尾时,您都会从头开始寻找“下一个”向量 - 然后可能会立即回到您开始时所在的同一向量。

      这是一个相对较小的错误(您应该只设置start=i+1),但请注意您也从未检查过您是否位于外部向量的末尾!好吧,你不应该在结束后对迭代器执行++,对吧?实际上,您应该能够在结束后到达 1 个单元格!所以这将是一个问题。您应该检查i==vec.size() 是否在某处。

      最后——除了这两个问题,代码看起来可以工作——但它很麻烦。它可以简单得多。如何?好吧,您从一开始就有 2 个不同的案例 - 检查是否为 j==vec[i].size()-1。我看到了逻辑——但试着换个角度想。在 C++ 中使用“最后一个元素之后的一个”来表示结束是一个很好的习惯用法。稍后你会看到这里也更好。但是检查你是否在最后的成语 - 或“使用良好” - 方法是j==vec[i].size(),所以当我看到size()-1时,我立即看到“事情可以更简单”。

      告诉我这可能更简单的另一件事是,您在两个不同的地方进行了相同的测试:测试当前内部向量中是否没有更多元素,因此您可以移动到下一个。你在一行中都这样做

      if (j==vec[i].size()-1)
      

      while(vec[start].size()==0)
      

      (检查当前向量是否为空,这意味着它没有剩余元素——因为它根本没有元素——因此你移动到下一个)

      这两件事(检查两次并使用size()-1)告诉我这个函数可以更简单。这是一个例子:

      myiterator& operator++(){
        j++; // First I increase j! Why? Because I want to get to "one after end" if it's the end
        while(j==vec[i].size()){ // in "iterator speak" this is equivalent to "(j==i->end())"
          i++;
          if (i==vec.size()) // in "iterator speak" this is "i==vec.end()"
            break;
          j=0; // in "iterator speak" this is "j=i->begin()"
        }
        return *this;
      }
      

      这似乎更短更优雅,尤其是如果您选择将 ij 更改为迭代器,它可以很容易地“看到”内部迭代器(这意味着您不需要保留引用vec!只有ij!)

      也尝试以这种方式创建operator--,如果您真的想要一个很好的练习来理解迭代器 - 像我建议的那样将ij 更改为迭代器本身没有参考@ 987654345@ 完全 看看你能不能让它工作:)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-21
        • 2022-07-21
        相关资源
        最近更新 更多