链接列表输出不同的值到cout

时间:2010-11-25 22:58:36

标签: c++ qt

我正在为我的作业写一个链表容器。使用Qt 4.7和gcc 4.4,我发现代码中存在一些问题,我猜它们与内存管理或垃圾收集有关。

使用<<运算符显示列表后,列表的所有数据都会更改。例如,在构建和设置像l

之类的列表之后
std::cout<<l<<std::endl;
std::cout<<l<<std::endl;

打印:

Data = [-10, 3, 2, 8, 1, -1, -2, ] // this is correct
Data = [0, 149560240, 149560192, 149558336, 149560256, 149558320, 149560208, ]

我的链接列表是:

#ifndef LINKEDLIST1_H_
#define LINKEDLIST1_H_

#include <iostream>

template<class T> class LinkedList1;
template<class T> class Node;

template<class T>
class Node
{
   friend class LinkedList1<T> ;
public:
   Node(const T& value) :
         Data(value), Next(NULL)
   {
   }
   Node() :
         Next(NULL)
   {
   }
   T Data;
   Node* Next;
};

template<class T>
class LinkedList1
{
public:
   LinkedList1() :
         size(-1), first(NULL)
   {
   }
   ~LinkedList1()
   {
      Node<T>* i = this->first;
      Node<T>* j = this->first;
      while(j!=NULL)
      {
         j=i->Next;
         delete i;
         i=j;
      }
   }
   // Operations on LinkedList
   Node<T>* First()
   {
      return first;
   }

   int Size()
   {
      return size + 1;
   }

   int Count()
   {
      int size = 0;
      Node<T>* current = this->firstFirst();
      while(current != NULL)
      {
         size++;
         current = current->Next;
      }
      this->size = size;
      return this->Size();
   }

   bool IsEmpty()
   {
      return this->Size() == 0;
   }

   void Prepend(Node<T>* value) //O(1)
   {
      value->Next = this->first;
      this->first = value;
      this->size++;
   }
   void Prepend(const T& value) //O(1)
   {
      Node<T>* item = new Node<T>(value);
      item->Next = this->first;
      this->first = item;
      this->size++;
   }
   void Append(Node<T>* value)
   {
      if(this->IsEmpty())
      {
         this->first = value;
         this->size++;
      }
      else
      {
         Node<T>* current = this->First();
         while(current->Next != NULL)
            current = current->Next;
         current->Next = value;
         value->Next = NULL;
         this->size++;
      }
   }
   void Append(const T& value)
   {
      Node<T>* temp= new Node<T>(value);
      this->Append(temp);
   }
   void Insert(Node<T>* location, Node<T>* value) //O(n)
   {
      Node<T>* current = this->first;
      Node<T>* before = current;
      while(current != NULL)
      {
         before = current;
         current = current->Next;
         if(current == location)
         {
            before->Next = value;
            value->Next = current;
            this->size++;
            break;
         }
      }
   }
   void Insert(Node<T>* location, const T& value)
   {
      Node<T>* temp = new Node<T>(value);
      this->Insert(location,temp);
   }

   Node<T>* Pop()
   {
      if(this->IsEmpty())
         return NULL;
      else
      {
         Node<T>* current = this->first;
         Node<T>* before = current;
         while(current->Next != NULL)
         {
            before = current;
            current = current->Next;
            before->Next = current;
         }
         before->Next = NULL;
         this->size--;
         return current;
      }
   }
   Node<T>* PopF()
   {
      if(!this->IsEmpty())
      {
         Node<T>* head = this->first;
         this->first = this->first->Next;
         this->size--;
         return head;
      }
      else
         return NULL;
   }
   Node<T>* Remove(Node<T>* location)
   {
      // validating by IsEmpty is not necessary for this operation,
      // while statement's condition guarantees validation
      Node<T>* current = this->first;
      Node<T>* before = current;
      while(current != NULL)
      {
         before = current;
         current = current->Next;
         before->Next = current;
         if(current == location)
         {
            before->Next = current->Next;
            current->Next=NULL;
            return current;
         }
      }
      return NULL; // Not found...
   }
   void Inverse()
   {
      if(this->IsEmpty())
         return;
      else
      {
         Node<T>* r = NULL;
         Node<T>* q = this->first;
         Node<T>* p = this->first;
         while(q != NULL)
         {
            p = p->Next;
            q->Next = r;
            r = q;
            q = p;
         }
         this->first = r;
      }
   }
   // Ordered insertion. implement this: foreach i,j in this; if i=vale: i+=vale, break; else if i<=value<=j: this.insert(j,value),break
   friend std::ostream& operator<<(std::ostream& out, const LinkedList1 item)
   {
      out<<"Data = [";
      Node<T>* current = item.first;
      while(current != NULL)
      {
         out << current->Data << ", ";
         current = current->Next;
      }
      out<<"]";
      return out;
   }

   void HelperOutput(std::ostream& out, const LinkedList1 item) const
   {
      out<<item;
   }

   Node<T>* operator[](const int& index)
   {
      int i=0;
      Node<T>* current = this->first;
      while(i<=index && current!=NULL)
      {
         if(i=index)
            return current;
         else
         {
            i++;
            current=current->Next;
         }
      }
   }
public:
   int size;
   Node<T>* first;

};

#endif /* LINKEDLIST1_H_ */

   friend std::ostream& operator<<(std::ostream& out, const LinkedList1 item)
   {
      out<<"Data = [";
      Node<T>* current = item.first;
      while(current != NULL)
      {
         out << current->Data << ", ";
         current = current->Next;
      }
      out<<"]";
      return out;
   }

第二次通话输出中的第一项始终为0。所以我想我已经在代码的某个地方将first设置为NULL;但我检查了所有的方法,没有类似的东西。另外,打印值不是指针本身;它的指针是Data。有人改变了我列表中所有Data的{​​{1}}个。

这是内存管理还是垃圾回收问题?如果没有,我做错了什么?

1 个答案:

答案 0 :(得分:5)

这里突出的一点是你的签名是:

std::ostream& operator<<(std::ostream& out, const LinkedList1 item)

而不是:

std::ostream& operator<<(std::ostream& out, const LinkedList1& item)

因此,您正在调用LinkedList的副本。我怀疑这里的问题是你没有正确实现LinkedList1的拷贝和赋值操作符,这样拷贝引用原始内容,析构函数使原始对象变成垃圾。

我建议将以下内容添加到LinkedList1的定义中:

private:
    // The following declarations disallow copy and assignment. Do not implement.
    LinkedList1(const LinkedList1&);
    LinkedList1& operator=(const LinkedList1&);

添加上述内容会导致您拥有原始签名的链接器错误。然后我建议通过const引用传递链表,你的问题就会消失。

顺便说一句,我注意到你的许多功能都可以const但不是。{1}}。例如,您有int Size()而不是int Size()const。通常应该将const标记为可以标记的任何东西。这被称为“const-correctness”,可以避免大量问题。

另外,小调风格的挑剔:你有if ... else语句,其中一个有大括号,另一个没有。我强烈建议您在所有情况下使用大括号,因为这会导致代码更易读。