队列:出队函数使程序崩溃
Queue: Dequeue function crashes program
我正在尝试使用双链表在 C++ 中创建一个队列。我还没有完全测试所有的东西,因为我被困在你出队的那一步。我试图创建一个临时节点,并四处移动东西,所以当我在队列(称为队列)的头节点上调用 delete 时,然后将头设置为下一个元素的临时节点,(你可以在代码),但是当我调用 delete 时,根据 MS Visual studios 2013,它是崩溃的地方。还要添加这有多奇怪,在调用堆栈之后,在调用 delete 之后,调用 setPrev 并设置 prev 节点并在那里崩溃。现在我从不在我的任何析构函数删除期间调用此函数,所以任何帮助都会起作用。我会尽力理解任何答案,但我对 C++ 术语还是陌生的。下面是我的代码。哦,最后一件事,总的来说,我所做的就是调用一次入队,然后出队一次,然后删除
Node Class
...
#ifndef TSDNODE_H
#define TSDNODE_H
template <class T>
class DNode
{
private:
DNode<T>* next;
DNode<T>* prev;
T data;
public:
DNode(T);
void setNext(DNode<T>* next);
void setPrev(DNode<T>* prev);
DNode<T>* getNext() const;
DNode<T>* getPrev() const;
T getData() const;
void setData(T data);
~DNode();
};
template <class T>
DNode<T>::DNode(T data)
{
this->next = nullptr;
this->data = data;
this->prev = nullptr;
}
template <class T>
void DNode<T>::setNext(DNode<T>* next)
{
this->next = next;
}
template <class T>
void DNode<T>::setPrev(DNode<T>* prev)
{
this->prev = prev;
}
template <class T>
DNode<T>* DNode<T>::getNext() const
{
return this->next;
}
template <class T>
DNode<T>* DNode<T>::getPrev() const
{
return this->prev;
}
template <class T>
T DNode<T>::getData() const
{
return this->data;
}
template <class T>
void DNode<T>::setData(T data)
{
this->data = data;
}
template <class T>
DNode<T>::~DNode()
{
delete this->next;
delete this->prev;
this->next = nullptr;
this->prev = nullptr;
}
#endif /* TSDNODE_H */
.....
Queue Class
.....
#ifndef TSQUEUE_H
#define TSQUEUE_H
#include "TSDNode.h"
#include <string>
template <class T>
class Queue
{
private:
DNode<T>* queue;
DNode<T>* tail;
int size;
public:
Queue();
void enqueue(T data);
T dequeue();
~Queue();
};
template <class T>
Queue<T>::Queue()
{
this->queue = nullptr;
this->tail = this->queue;
size = 0;
}
template <class T>
void Queue<T>::enqueue(T data)
{
if (this->tail != NULL)
{
this->tail->setNext(new DNode<T>(data));
this->tail->getNext()->setPrev(this->tail);
this->tail = this->tail->getNext();
}
else
{
this->queue = new DNode<T>(data);
this->tail = this->queue;
}
size++;
}
template <class T>
T Queue<T>::dequeue()
{
T data;
if (this->queue == nullptr)
{
delete this->tail;
delete this->queue;
this->tail = nullptr;
std::string ex = "Exception: Empty Queue\n";
throw ex;
}
else if (this->queue != nullptr)
{
data = this->queue->getData();
DNode<T>* node = this->queue->getNext();
this->queue->setNext(nullptr);
this->queue->setPrev(nullptr);
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
delete this->queue;
this->queue = node;
}
size--;
return data;
}
template <class T>
Queue<T>::~Queue()
{
delete this->queue;
this->queue = nullptr;
this->tail = nullptr;
}
#endif /* TSQUEUE_H */
在您的 DNode
析构函数中,您不想删除 next
和 prev
节点。您只想删除此节点,而不是它链接到的所有内容。
删除这些行
delete this->next;
delete this->prev;
编辑:实际上这不是您的问题,因为您在删除节点之前清除了 next
和 prev
值。我仍然认为最好不要自动删除整个链,但只要您处理节点删除的方式一致,它应该仍然有效。
你实际上的问题是,当你将最后一个节点出队时,你仍然尝试在这一行中设置下一个节点的 next
指针:
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
此时 node
是 nullptr,因此尝试访问 node->next
会导致崩溃。一个简单的 if 测试就是你所需要的
if (node != nullptr)
node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here
编辑 2:
另请注意,在队列中的下一个节点为 nullptr
的情况下,您还希望将尾部设置为 nullptr
.
我正在尝试使用双链表在 C++ 中创建一个队列。我还没有完全测试所有的东西,因为我被困在你出队的那一步。我试图创建一个临时节点,并四处移动东西,所以当我在队列(称为队列)的头节点上调用 delete 时,然后将头设置为下一个元素的临时节点,(你可以在代码),但是当我调用 delete 时,根据 MS Visual studios 2013,它是崩溃的地方。还要添加这有多奇怪,在调用堆栈之后,在调用 delete 之后,调用 setPrev 并设置 prev 节点并在那里崩溃。现在我从不在我的任何析构函数删除期间调用此函数,所以任何帮助都会起作用。我会尽力理解任何答案,但我对 C++ 术语还是陌生的。下面是我的代码。哦,最后一件事,总的来说,我所做的就是调用一次入队,然后出队一次,然后删除
Node Class
...
#ifndef TSDNODE_H
#define TSDNODE_H
template <class T>
class DNode
{
private:
DNode<T>* next;
DNode<T>* prev;
T data;
public:
DNode(T);
void setNext(DNode<T>* next);
void setPrev(DNode<T>* prev);
DNode<T>* getNext() const;
DNode<T>* getPrev() const;
T getData() const;
void setData(T data);
~DNode();
};
template <class T>
DNode<T>::DNode(T data)
{
this->next = nullptr;
this->data = data;
this->prev = nullptr;
}
template <class T>
void DNode<T>::setNext(DNode<T>* next)
{
this->next = next;
}
template <class T>
void DNode<T>::setPrev(DNode<T>* prev)
{
this->prev = prev;
}
template <class T>
DNode<T>* DNode<T>::getNext() const
{
return this->next;
}
template <class T>
DNode<T>* DNode<T>::getPrev() const
{
return this->prev;
}
template <class T>
T DNode<T>::getData() const
{
return this->data;
}
template <class T>
void DNode<T>::setData(T data)
{
this->data = data;
}
template <class T>
DNode<T>::~DNode()
{
delete this->next;
delete this->prev;
this->next = nullptr;
this->prev = nullptr;
}
#endif /* TSDNODE_H */
.....
Queue Class
.....
#ifndef TSQUEUE_H
#define TSQUEUE_H
#include "TSDNode.h"
#include <string>
template <class T>
class Queue
{
private:
DNode<T>* queue;
DNode<T>* tail;
int size;
public:
Queue();
void enqueue(T data);
T dequeue();
~Queue();
};
template <class T>
Queue<T>::Queue()
{
this->queue = nullptr;
this->tail = this->queue;
size = 0;
}
template <class T>
void Queue<T>::enqueue(T data)
{
if (this->tail != NULL)
{
this->tail->setNext(new DNode<T>(data));
this->tail->getNext()->setPrev(this->tail);
this->tail = this->tail->getNext();
}
else
{
this->queue = new DNode<T>(data);
this->tail = this->queue;
}
size++;
}
template <class T>
T Queue<T>::dequeue()
{
T data;
if (this->queue == nullptr)
{
delete this->tail;
delete this->queue;
this->tail = nullptr;
std::string ex = "Exception: Empty Queue\n";
throw ex;
}
else if (this->queue != nullptr)
{
data = this->queue->getData();
DNode<T>* node = this->queue->getNext();
this->queue->setNext(nullptr);
this->queue->setPrev(nullptr);
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
delete this->queue;
this->queue = node;
}
size--;
return data;
}
template <class T>
Queue<T>::~Queue()
{
delete this->queue;
this->queue = nullptr;
this->tail = nullptr;
}
#endif /* TSQUEUE_H */
在您的 DNode
析构函数中,您不想删除 next
和 prev
节点。您只想删除此节点,而不是它链接到的所有内容。
删除这些行
delete this->next;
delete this->prev;
编辑:实际上这不是您的问题,因为您在删除节点之前清除了 next
和 prev
值。我仍然认为最好不要自动删除整个链,但只要您处理节点删除的方式一致,它应该仍然有效。
你实际上的问题是,当你将最后一个节点出队时,你仍然尝试在这一行中设置下一个节点的 next
指针:
node->setPrev(nullptr);
//--------------------------------------------------- crashes here
此时 node
是 nullptr,因此尝试访问 node->next
会导致崩溃。一个简单的 if 测试就是你所需要的
if (node != nullptr)
node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here
编辑 2:
另请注意,在队列中的下一个节点为 nullptr
的情况下,您还希望将尾部设置为 nullptr
.