C++ 链表队列指针导致未定义的行为

C++ Linked List Queue pointers causing undefined behavior

我已阅读问题但未看到我的答案。 大多数人为此使用结构,在测试参考代码后,我发现结构版本可以使用,但是为什么 class 版本不行?

#include <iostream>
using namespace std;

// I'm still bad at pointer logic but it makes sense.
// REFERENCES
// https://www.geeksforgeeks.org/queue-linked-list-implementation/
// stack linked list assignment earlier in semester
// 
class Node {
    public:
    int data;
    Node *next;         // controls flow of nodes
};

class Queue {
    public:
    Queue();
    ~Queue();
    void enQueue(int data);
    void deQueue();
    bool isEmpty();
    
    //private: all set to public because I don't want to make a print function
    Node *front;
    Node *rear;
    int counter;
};

Queue::Queue()

{
    
    front = NULL;
    rear  = NULL;
    
}

Queue::~Queue() {
    
    if (rear == NULL && front == NULL)
    {
        cout << "Nothing to clean up!" << endl;
    }
    else
    {
        cout << "Delete should be happening now...";
    }
}

void Queue::enQueue(int data) {

    // create new node of queue structure
    Node *temp  = new Node;
    temp->data  = data;
    
    // write like this line below if not temp->data = data;
    // Node *temp = new Node(data); 
    
    // if the queue is empty, first node.
    if (rear == NULL)
    {
        front = temp;
        rear  = temp;
        return;
    }
    
    // assign data of queue structure

    rear->next  = temp; // point rear pointer to next pointer = assign to temp
    rear = temp; // assign rear to temp keep front pointer at beginning fifo
}

void Queue::deQueue()
{

    // if queue is empty, return NULL
    if (front == NULL)
    {
        cout << "Queue is empty, sorry!";

        return;
    }
    
    Node*   temp = front;       // assign front 
    
    //problem here
    front = front->next;        // move front one node ahead
    
    if(front == NULL)
    {
     rear = NULL;
    }
     delete (temp);
    
    return;
    }
    
bool Queue::isEmpty() 
{
    //   cout << "functions";
    //   cout << endl;
    return (front == NULL && rear == NULL);
}

int main()
{
    Queue yay;
    yay.isEmpty();
    yay.deQueue();
    cout << endl;
    yay.enQueue(5);
    yay.enQueue(6);


    cout << "Queue Front : " << (yay.front)->data << endl;
    yay.deQueue();
    cout << "After deqQueue " << endl;
    cout << "Queue Front : " << (yay.front)->data << endl;
    yay.deQueue();
    cout << "Queue Front : " << (yay.front)->data << endl;
    yay.deQueue(); // <- Problem here
    yay.deQueue();
    cout << "completed" << endl;
}

我已将问题隔离到第 90 行

    //problem here
front = front->next;        // move front one node ahead

它导致 int main() 中的这段代码不打印

    yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;

我知道我在指针指向等方面很弱,所以如果能告诉我我没有看到的地方,我将不胜感激,我已经研究了一段时间,但没有解决。

此link代码通过在线gdb

https://onlinegdb.com/0B0KzcHMa

This is the output with line 
Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 6

And the output with line 90 and 96 commented out //96 commented to avoid double free


Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 5
Queue Front : 5
completed
Delete should be happening now...


Now I know, I know I should be better at this traversal of nodes business 
but, I am not seeing it and this may help me remember it in the future :X

I believe its a simple fix but, everything I try reaches the former output
rather than the later with intended data represented, I believe it is
nexting out into random memory making memory leak or memory pointing wherever
thus it never goes back to main to complete terminal messages

问题出在这里:

    Queue yay;
    yay.isEmpty();
    yay.deQueue();
    cout << endl;
    yay.enQueue(5);
    yay.enQueue(6);


    cout << "Queue Front : " << (yay.front)->data << endl;
    yay.deQueue();
    cout << "After deqQueue " << endl;
    cout << "Queue Front : " << (yay.front)->data << endl;
    yay.deQueue();
    cout << "Queue Front : " << (yay.front)->data << endl; // <<==== HERE

队列插入了两个元素 5 和 6。然后一个被弹出,然后另一个。这意味着 yay.front 现在是 nullptr 根据您阅读列表末尾的 deQueue 逻辑。因此,读取 (yay.front)->data 通过取消引用无效指针(在本例中为包含 nullptr 的指针)调用 未定义行为

失去该取消引用(一种或另一种方式)并且代码不应再出错。