0

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

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和基本的。提前致谢。

4

3 回答 3

2

到目前为止看起来不错。我会说

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

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

于 2013-11-10T20:52:48.683 回答
1

约翰已经回答了你关于operator->. 我只是想评论operator++and 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 个不同的案例 - 检查 if 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--这样做,如果你真的想要一个很好的练习来理解迭代器 - 像我建议的那样改变i迭代j器本身而不需要参考vec 看看你是否可以让它工作:)

于 2013-11-10T21:21:01.043 回答
0

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

于 2013-11-10T20:57:24.230 回答