我正在为我的作业写一个链表容器。使用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}}个。
这是内存管理还是垃圾回收问题?如果没有,我做错了什么?
答案 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语句,其中一个有大括号,另一个没有。我强烈建议您在所有情况下使用大括号,因为这会导致代码更易读。