Iterator构造函数未正确初始化

时间:2016-02-17 23:29:43

标签: c++

我正在用一个interator编写一个HeapPriorityQueue类。问题是当.begin()函数调用Iterator构造函数时,它进入基类的复制赋值构造函数(HeapPriorityQueue类)。我初始化了所有变量,但是当它们通过Iterator构造函数时,它们就会丢失。我不明白为什么。我尝试在体内初始化它们但调试器不会执行身体,我认为这很奇怪。

我只是将代码条带化得足够低,以便其他人可以快速理解。我要添加的唯一注释是为了确定我在模板中使用gt()函数或tgt的优先级。

感谢任何帮助,谢谢

template<class T, bool (*tgt)(const T& a, const T& b) = nullptr> class HeapPriorityQueue {
  public:
    //Destructor/Constructors
    ~HeapPriorityQueue();

    HeapPriorityQueue          (bool (*cgt)(const T& a, const T& b) = nullptr);
    HeapPriorityQueue          (const HeapPriorityQueue<T,tgt>& to_copy, bool (*cgt)(const T& a, const T& b) = nullptr);

    class Iterator {
      public:
        //Private constructor called in begin/end, which are friends of HeapPriorityQueue<T,tgt>
        ~Iterator();
        T           erase();
        std::string str  () const;
        HeapPriorityQueue<T,tgt>::Iterator& operator ++ ();
        HeapPriorityQueue<T,tgt>::Iterator  operator ++ (int);


        friend Iterator HeapPriorityQueue<T,tgt>::begin () const;
        friend Iterator HeapPriorityQueue<T,tgt>::end   () const;

      private:
        //If can_erase is false, the value has been removed from "it" (++ does nothing)
        HeapPriorityQueue<T,tgt>  it;                 //copy of HPQ (from begin), to use as iterator via dequeue
        HeapPriorityQueue<T,tgt>* ref_pq= nullptr;
        int                      expected_mod_count=0;
        bool                     can_erase = true;

        //Called in friends begin/end
        //These constructors have different initializers (see it(...) in first one)
        Iterator(HeapPriorityQueue<T,tgt>* iterate_over, bool from_begin);    // Called by begin
        Iterator(HeapPriorityQueue<T,tgt>* iterate_over);                     // Called by end
    };


    Iterator begin () const;
    Iterator end   () const;


  private:
    bool (*gt) (const T& a, const T& b); // The gt used by enqueue (from template or constructor)
    T*  pq;                              // Array represents a heap, so it uses heap ordering property
    int length    = 0;                   //Physical length of pq array: must be >= .size()
    int used      = 0;                   //Amount of array used:  invariant: 0 <= used <= length
    int mod_count = 0;                   //For sensing concurrent modification
  };


template<class T, bool (*tgt)(const T& a, const T& b)>
HeapPriorityQueue<T,tgt>::HeapPriorityQueue(const HeapPriorityQueue<T,tgt>& to_copy, bool (*cgt)(const T& a, const T& b))
: gt(tgt != nullptr ? tgt : cgt), length(to_copy.length) {
    if (gt == nullptr)
        gt = to_copy.gt;//throw TemplateFunctionError("HeapPriorityQueue::copy constructor: neither specified");
      if (tgt != nullptr && cgt != nullptr && tgt != cgt)
        throw TemplateFunctionError("HeapPriorityQueue::copy constructor: both specified and different");

      pq = new T[length];

      if (gt == to_copy.gt)
        used = to_copy.used;

      for (int i=0; i<to_copy.used; ++i)
         enqueue(to_copy.pq[i]);
}

template<class T, bool (*tgt)(const T& a, const T& b)>
auto HeapPriorityQueue<T,tgt>::begin () const -> HeapPriorityQueue<T,tgt>::Iterator {
     return Iterator(const_cast<HeapPriorityQueue<T,tgt>*>(this),true);}

template<class T, bool (*tgt)(const T& a, const T& b)>
HeapPriorityQueue<T,tgt>::Iterator::Iterator(HeapPriorityQueue<T,tgt>* iterate_over, bool tgt_nullptr):
it(*ref_pq),ref_pq(iterate_over),expected_mod_count(ref_pq->mod_count){}

1 个答案:

答案 0 :(得分:0)

  

我初始化了所有变量,但是当它们通过Iterator构造函数时,它们就会丢失。

变量总是按照它们声明的顺序初始化,所以让我们看一下:

    //If can_erase is false, the value has been removed from "it" (++ does nothing)
    HeapPriorityQueue<T,tgt>  it;                 //copy of HPQ (from begin), to use as iterator via dequeue
    HeapPriorityQueue<T,tgt>* ref_pq= nullptr;
    int                      expected_mod_count=0;
    bool                     can_erase = true;

然后:

HeapPriorityQueue<T,tgt>::Iterator::Iterator(HeapPriorityQueue<T,tgt>* iterate_over, bool tgt_nullptr):
it(*ref_pq),ref_pq(iterate_over),expected_mod_count(ref_pq->mod_count){}

首先,您将it初始化为*ref_pq,即*nullptr,这是非法的,通常会立即崩溃。我没有真正费心去分析这一点,但我确实有一个问题。为什么在世界上你的“指针”包含它试图迭代的整个数据集的副本?不要那样做。另外,我不知道你对expected_mod_count的意图,但这可能也是一个坏主意。您的tgt模板参数也是如此。

供您审核:Writing your own STL Container