如何在迭代器中正确引用第一个向量容器?

问题描述 投票:-1回答:1

现在,我正在尝试创建一个模板类Set,它包含一个带有迭代器的泛型类型<T>。虽然我不太明白目的是什么,但我仍然希望为迭代器创建一个所谓的“end sentinel”:

while(start != end)
   cout << start++ << endl;

startend指的是我认为是向量的开始和结束。到目前为止,我已经创建了一个模板类,在其中创建了一个迭代器。在我的主要内容中,我插入10个整数,然后尝试使用我的“end sentinel”。我的代码看起来像这样:

#include <iostream>
#include <vector>

using namespace std;

template <class T>
class Set{
     vector<T> theSet;
public:
    Set() {}
    Set(const Set& s): theSet(s.theSet){}
    ~Set(){theSet.clear();}

void insert(T t){
    cout << "inserted " << t << endl;
    theSet.push_back(t);
}

class iterator;
friend class iterator;
class iterator{
    Set<T>& s;
    int index;
public:
    iterator(Set<T>& is) : s(is), index(0) {}
    iterator(Set<T>& is, bool) : s(is) {}

   T operator*(){
        return s.theSet.at(index);          
   }

    T operator++(){
        return ++s.theSet.at(index);
    }
    T operator++(int){
        return s.theSet.at(index)++;
    }
    bool operator!=(const iterator& ri)const {return index!=ri.index;}
};

iterator begin() {return iterator (*this);}
//Create the end sentinel:
iterator end() {return iterator (*this, true); } 

};

int main()
{
    Set<int> other;

for(int i=0; i<10; ++i){
    other.insert(i);
}

/*
for(Set<int>::iterator start = other.begin(); start != other.end(); start++){
    cout << *start << endl;
}

cout << "\n\n Program ends succesfully" << endl;
*/

Set<int>::iterator start = other.begin();
Set<int>::iterator end = other.end();


while(start != end){
    cout << start++ << endl;
}
return 0;
}

当我在课程结束时引用startend时,问题出现了:

iterator begin() {return iterator (*this);}
//Create the end sentinel:
iterator end() {return iterator (*this, true); }

看来,begin()用第一个构造函数返回iteratorend()用第二个构造函数返回iterator,因为后者接受两个参数。但是,我得到的第二个构造函数看起来像

iterator(Set<T>& is, bool) : s(is) {}

我不确定这是如何引用容器的“结束”的。我怎样才能以正确的方式引用它?

c++ vector iterator containers
1个回答
0
投票

这里有一些示例代码。这仅用于演示目的!这段代码效率不高,现实世界中缺少很多功能!

#include <iostream>

using namespace std;

template <typename T>
class Set {
  int sz;
  T* elems;

 public:
  Set() : sz{0}, elems{nullptr} {}
  Set(int n) : sz{n}, elems{new T[n]} {}
  ~Set() { delete[] elems; }

  class Iterator;

  Iterator begin() { return Iterator{elems}; }
  Iterator end() {
    return Iterator{elems + sz};
  }  // points to past-the-end of elems
     // for example if sz=5:
     // 1 2 3 4 5 | 6
     // |           |
     // begin()    end()


  Iterator insert(T t) {
    // check if the element t exists in the set
    //    -> if so, then return the pointer to the existing element
    //    -> otherwise return the pointer to the newly inserted element
    // BUT:this is very inefficient !!!
    // in a real world code one would use
    // some kind of binary try for holding 
    // the keys/values of the set
    for (int i = 0; i < sz; i++)
      if (elems[i] == t)
        return Iterator{elems+i};

    T* new_elems = new T[sz + 1];
    for (int i = 0; i < sz; ++i)
      new_elems[i] = elems[i];

    new_elems[sz++] = t;
    delete[] elems;
    elems = new_elems;

    return Iterator{elems+sz};
  }

  class Iterator {
   public:
    Iterator() : p{nullptr} {}
    Iterator(T* pp) : p{pp} {}

    T* operator++() { return ++p; }  // pre-increment, ex. ++iter
    T* operator++(int) { return p++; } // post-increment, ex. iter++

    T& operator*() { return *p; }

    const T& operator*() const { return *p; }

    bool operator==(const Iterator& rhs) const { return p == rhs.p; }

    bool operator!=(const Iterator& rhs) const { return !this->operator==(rhs); }

   private:
    T* p;
  };  // Iterator

};    // Set

int main() {

  Set<int> s;
  s.insert(1);
  s.insert(2);
  s.insert(3);
  s.insert(4);

  for (Set<int>::Iterator it=s.begin(); it != s.end(); ++it)
    std::cout << *it << std::endl;
}

这是输出:https://wandbox.org/permlink/LT4F2CAkZhFCCcZw

© www.soinside.com 2019 - 2024. All rights reserved.