I've read the questions and not seen answer to mine. Most people use structs for these and after testing reference code I see the struct version is functional but, why is class version not?
#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
// https://stackoverflow.com/questions/29787026/c-queue-from-linked-list
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;
}
I've isolated the problem to line 90
//problem here
front = front->next; // move front one node ahead
it causes this code in int main() to not print
yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;
I know I am weak at pointer directing and so forth, so if could please tell me what I am not seeing would be appreciated, I've been poking at it for a while now and did not resolve.
This link for code through online 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
CodePudding user response:
The problem is here:
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
The queue had two elements, 5 and 6, inserted. Then one was popped, then the other. That means yay.front
is now nullptr
per your deQueue
logic reading the end of the list. Therefore, reading (yay.front)->data
invoke undefined behavior by dereferencing an invalid pointer (in this case a pointer containing nullptr
).
Lose that dereference (one way or another) and the code shouldn't fault any longer.