【问题标题】:Queue: Dequeue function crashes program队列:出列函数使程序崩溃
【发布时间】:2015-03-28 23:03:56
【问题描述】:

我正在尝试使用双链表在 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 */

【问题讨论】:

  • @Golazo 这是一个 C++ 问题。您尝试在“C”标签中进行编辑是完全不合适的。如果不确定,请不要尝试添加标签。

标签: c++ list queue


【解决方案1】:

在您的DNode 析构函数中,您不想删除nextprev 节点。您只想删除此节点,而不是它链接到的所有内容。

删除这些行

delete this->next;
delete this->prev;

编辑:实际上这不是您的问题,因为您在删除节点之前清除了 nextprev 值。我仍然认为最好不要自动删除整个链,但只要您与处理节点删除的方式保持一致,它仍然可以工作。

你实际上的问题是当你出列最后一个节点时,你仍然尝试在这一行设置下一个节点的next指针:

node->setPrev(nullptr);
//--------------------------------------------------- crashes here 

此时node 为nullptr,因此尝试访问node-&gt;next 会导致崩溃。只需一个简单的 if 测试即可

if (node != nullptr)
    node->setPrev(nullptr);
//--------------------------------------------------- no longer crashes here 

编辑 2: 另请注意,如果队列中的下一个节点是nullptr,您还需要将尾部设置为nullptr

【讨论】:

  • 有道理,我想我添加它的原因是,在我的课堂上,来自使用节点的链表。我想创建一个通用节点类,可以处理任何东西,包括链表,我总是被教导这样做,所以当你删除链表的头部时,它会链接并删除链表中的所有节点,所以这是我修复它的唯一方法吗?顺便说一句,谢谢
  • 如果在删除头节点的时候自动删除了链表中的所有节点,那么就没有办法自行删除头节点了。最好让节点对自己负责,而不是让所有兄弟节点负责。实际上 - 看看你的代码这不是你的问题 - 我会更新我的答案。
  • 感谢大家的帮助:)
猜你喜欢
  • 1970-01-01
  • 2017-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多