【发布时间】:2013-12-21 18:51:23
【问题描述】:
我有一个创建节点并将它们插入双向链表的分配。其中一个规范是包含一个析构函数。由于某种原因,当我在 main 中调用 addSortedList() 时,我的析构函数似乎正在删除对象或指针或两者。如果我取出析构函数,程序运行得很好,当调用 addSortedList() 时程序会崩溃。今天我什至花了一些时间和我的导师在一起,他说我的析构函数看起来很好,但不知道是什么导致了问题。有人可以向我解释为什么会这样吗?
#include <iostream>
using namespace std;
template <typename T>
class DoublyLinkedList;
template <typename T>
class Node
{
friend class DoublyLinkedList<T>;
public:
Node();
Node(const T& data, Node<T> *next, Node<T> *prev);
private:
T data;
Node<T> *next;
Node<T> *prev;
}; // end class Node
//*******************************************************************
// Create a header node for an empty linked list.
template <typename T>
Node<T>::Node()
{
next = this;
prev = this;
}
//*******************************************************************
// Create a regular node to be inserted into a linked list
template <typename T>
Node<T>::Node(const T& data, Node<T> *next, Node<T> *prev)
{
this->data = data;
this->next = next;
this->prev = prev;
}
//*******************************************************************
template <typename T>
class DoublyLinkedList
{
public:
DoublyLinkedList();
DoublyLinkedList(const T arr[], int arrSize);
~DoublyLinkedList();
void insert(Node<T> *insertionPoint, const T& data);
void display();
DoublyLinkedList<T> addSortedList(const DoublyLinkedList<T>& list2);
private:
Node<T> *header; // pointer to header node (header points to
// front and back of list)
int size; // number of data nodes in list
}; // end class DoublyLinkedList
//*******************************************************************
// Default constructor creates only a header node
template <typename T>
DoublyLinkedList<T>::DoublyLinkedList()
{
header = new Node<T>();
size = 0;
} // end constructor
//*******************************************************************
// Constructor takes in array and array size and creates a doubly
// linked list with a header node.
template <typename T>
DoublyLinkedList<T>::DoublyLinkedList(const T arr[], int arrSize)
{
header = new Node<T>();
size = arrSize;
for (int i = size - 1; i > -1; i--)
{
insert(header->next, arr[i]);
}
} // end constructor
//*******************************************************************
// Destructor to delete nodes after use.
template <typename T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
Node<T> *oldFrontPointer; // pointer to node to be deleted
Node<T> *newFrontPointer; // pointer to next node to be deleted
oldFrontPointer = header->next;
while (oldFrontPointer->next != header)
{
newFrontPointer = oldFrontPointer->next;
delete oldFrontPointer;
oldFrontPointer = newFrontPointer;
}
delete header;
} // end destructor
//*******************************************************************
// This function inserts a new node into a list
template <typename T>
void DoublyLinkedList<T>::insert(Node<T> *insertionPoint, const T& data)
{
Node<T> *prevNodePtr; // pointer to node that precedes insertionpoint
Node<T> *newNodePtr; // pointer to new node
prevNodePtr = insertionPoint->prev;
newNodePtr = new Node<T>(data, insertionPoint, prevNodePtr);
size++;
insertionPoint->prev = prevNodePtr->next = newNodePtr;
} // end insert
//*******************************************************************
// This function prints the node data from a list
template <typename T>
void DoublyLinkedList<T>::display()
{
Node<T> *currentNodePtr = header->next;
if (size == 0)
{
cout << "Empty linked list.";
}
else
{
while (currentNodePtr != header)
{
cout << currentNodePtr->data << " ";
currentNodePtr = currentNodePtr->next;
}
}
cout << "\n";
} // end display
//*******************************************************************
// This function merges the parameter list into the calling object
// list in sorted order assuming both lists are presorted.
template <typename T>
DoublyLinkedList<T> DoublyLinkedList<T>::
addSortedList(const DoublyLinkedList<T>& list2)
{
Node<T> *list1Pointer = this->header->next;
Node<T> *list2Pointer = list2.header->next;
while (list1Pointer != this->header && list2Pointer->next != list2.header)
{
// insert list 2 nodes if they are smaller than list 1 current node
if (list1Pointer->data > list2Pointer->data)
{
insert(list1Pointer, list2Pointer->data);
list2Pointer = list2Pointer->next;
}
// move list 1 pointer if list 1 current node is smaller than
// list 2 current node
else if (list1Pointer->data < list2Pointer->data)
{
list1Pointer = list1Pointer->next;
}
// insert list 2 nodes that are smaller than list 1 current node
else if (list1Pointer->next == this->header)
{
insert(list1Pointer, list2Pointer->data);
list2Pointer = list2Pointer->next;
}
}// end while
// insert last list 2 nodes that are larger than last node in
// list 1 at the end of the list
while (list1Pointer->next == this->header && list2Pointer != list2.header)
{
list1Pointer = list1Pointer->next;
insert(list1Pointer, list2Pointer->data);
list2Pointer = list2Pointer->next;
}
return *this;
} // end addSortedList
int main()
{
int arrA[] = {20,80,100};
int arrB[] = {10,30,60,100,110};
int arrASize = sizeof(arrA)/sizeof(int);
int arrBSize = sizeof(arrB)/sizeof(int);
DoublyLinkedList<int> listA(arrA, arrASize);
DoublyLinkedList<int> listB(arrB, arrBSize);
DoublyLinkedList<int> listC;
listC.display();
listA.display();
listB.display(); //extra
listA.addSortedList(listB);
listA.display();
listB.display();
} // end main
【问题讨论】:
-
你没有遵循三法则。
-
克里斯所说的。有关更多信息,请阅读此处 (stackoverflow.com/questions/4172722/what-is-the-rule-of-three) - 您需要为您的类定义一个复制构造函数和赋值运算符。
-
这与问题本身无关。在简单的情况下依赖默认的复制构造函数并没有错。
-
当你的班级维护
Node<T> *header;- 这正是三巨头的规则^^ -
当您错误地或匆忙地在 15 个标头之外实施浅拷贝并忘记它时,此规则不会保护您免于假设深拷贝。规则很好,但不能代替问题分析。
标签: c++ templates destructor