Error on build but no compile errors - c++

I am having some trouble with my homework and could use your help.
I am getting some sort of error when I try to run my program. When i compile it i get the success mssage but when i try to run it i get a popup with the error "Unhandled exception at 0x011b18d2 in Project 2.exe: 0xC0000005: Access violation reading location 0xccccccd0." If anyone can help me i would appreciate it, thank you.
This is the code i was assigned to build on (this cannot be changed)
#include <iostream >
#include "stack.h"
using namespace std ;
int main ()
{
Stack < int > s1 , s2 ;
int element ;
s1 . push (1); s1 . push (2); s1 . push (3);
s1 . pop ( element );
cout << " s1 popped element : " << element << endl ;
s2 = s1 ;
s2 . push (4);
s2 . pop ( element );
cout << " s2 popped element : " << element << endl ;
s1 . pop ( element );
cout << " s1 popped element : " << element << endl ;
s2 . makeEmpty ();
s2 . isEmpty () ? cout << " s2 is empty \n": cout << " s2 is not empty \n ";
system ("pause");
return 0;
}
This is what i wrote to compliment the code above
template <class DataType>
struct Node{
DataType info;
Node<DataType>*next;
};
template <class DataType>
class Stack
{
public:
Stack();
void push(DataType elementToPush);
bool pop(DataType & poppedElement);
bool peek(DataType & topElement);
Stack(const Stack<DataType> &element); // Copy constructor
~Stack(); // Destructor
Stack<DataType> & operator=(const Stack<DataType> &element); //Overload assignment operator
bool isEmpty()const;
void makeEmpty();
private:
Node<DataType>*top;
Node<DataType>*header;
inline void deepCopy(const Stack<DataType> & original);
};
template<class DataType>
Stack<DataType>::Stack()
{
Node<DataType>*top=new Node<DataType>;
}
template<class DataType> // Remove the node at the front of the list and return the element
bool Stack<DataType>::pop(DataType & poppedElement)
{
Node<DataType>*ptr=top;
ptr=ptr->next;
Node<DataType>*ptr2=ptr->next;
top->next=ptr2;
poppedElement = ptr->info;
delete ptr;
return true;
}
template<class DataType> // Return the element at the front of the list wothout deleting it
bool Stack<DataType>::peek(DataType & topElement)
{
if(top->next==NULL)
return false;
topElement=top->next->info;
return true;
}
template<class DataType> // Make a new node for the element and push it to the front of the list
void Stack<DataType>::push(DataType elementToPush)
{
Node<DataType>*ptr=top;
Node<DataType>*ptr2=new Node<DataType>;
ptr2->info=elementToPush;
ptr2->next=ptr->next;
ptr->next=ptr2;
}
template<class DataType> // Check to see if the list is empty
bool Stack<DataType>::isEmpty()const
{
return top->next==NULL;
}
template<class DataType> // Empry the list out
void Stack<DataType>::makeEmpty()
{
Node<DataType>*ptr=top;
while(top->next != NULL)
{
while(ptr->next != NULL)
ptr->next;
delete ptr->next;
}
}
template<class DataType> // Deep copy
inline void Stack<DataType>::deepCopy(const Stack<DataType> & original)
{
Node<DataType>*copyptr=new Node<DataType>;
Node<DataType>*originalptr=top;
while(originalptr != NULL)
{
originalptr=originalptr->next;
copyptr->next=new Node<DataType>;
copyptr->info=originalptr->info;
}
}
template<class DataType> // Copy Constructor
Stack<DataType>::Stack(const Stack<DataType> &element)
{
deepCopy(element);
}
template<class DataType> // Destructor
Stack<DataType>::~Stack()
{
makeEmpty();
}
template<class DataType> // Overload assignment operator
Stack<DataType> & Stack<DataType>::operator=(const Stack<DataType> &element)
{
if(this == &element)
return *this;
makeEmpty();
deepCopy(element);
return *this;
}

I got pushback on my previous answer. Maybe this one will be better received. If you don't like my choice of white space, that is what pretty-printers are for. The code below is the original code reformatted. My thoughts are included as interlinear gloss.
Node is an implementation detail of your Stack. It should be scoped as a private type declaration, putting here pollutes the namespace. Also, if this class had a constructor that either initialized next to nullptr or required it to be set explicitly, some bugs, such as the one you found, would be easier to diagnose. As it stands, after Node is constructed, next can point to a random memory location.
template <class DataType>
struct Node {
DataType info;
Consider using a smart pointer here.
Node<DataType>* next; };
template <class DataType>
class Stack {
public:
Stack();
The argument should be const& to avoid extra copying.
void push(DataType elementToPush);
bool pop(DataType& poppedElement);
This can be a const method.
bool peek(DataType& topElement);
element is a poor name. The copy constructor copies an entire stack, not just an element.
Stack(const Stack<DataType>& element); // Copy constructor
~Stack(); // Destructor
Stack<DataType>& operator=(const Stack<DataType>&
element); //Overload assignment operator
bool isEmpty() const;
void makeEmpty();
private:
Consider using a smart pointer here.
Node<DataType>* top;
header is not used. It should be deleted.
Node<DataType>* header;
inline void deepCopy(const Stack<DataType>& original); };
template<class DataType>
Stack<DataType>::Stack() {
top should be initialized to nullptr in a member initialization list. The empty node you
are using here is not required, it makes you code more complex, and you end up leaking it later.
Also, this is a major bug. You are assigning to a local here, not the member variable!
Node<DataType>* top = new Node<DataType>; }
template<class DataType> // Remove the node at the front of the list and return the element
bool Stack<DataType>::pop(DataType& poppedElement) {
If you want ptr to be top->next just say that.
Node<DataType>* ptr = top;
ptr = ptr->next;
This ptr2 variable is not needed. You just need top->next = top->next->next. Also note that the empty head element is adding noise here.
Node<DataType>* ptr2 = ptr->next;
top->next = ptr2;
poppedElement = ptr->info;
delete ptr;
You need to have tested for underflow to return false in that case.
return true; }
People are pretty forgiving about comments, but it is best if they are properly spelled and punctuated.
template<class DataType> // Return the element at the front of the list wothout deleting it
bool Stack<DataType>::peek(DataType& topElement) {
if (top->next == NULL) {
return false; }
topElement = top->next->info;
return true; }
template<class DataType> // Make a new node for the element and push it to the front of the list
void Stack<DataType>::push(DataType elementToPush) {
This variable is meaningless, just use top.
Node<DataType>* ptr = top;
ptr2 can be constructed with the values you need instead of being mutated afterwards. Try auto ptr2 = new Node<DataType> { elementToPush, ptr->next };. Also, consider using a smart pointer.
Node<DataType>* ptr2 = new Node<DataType>;
ptr2->info = elementToPush;
ptr2->next = ptr->next;
ptr->next = ptr2; }
template<class DataType> // Check to see if the list is empty
bool Stack<DataType>::isEmpty()const {
return top->next == NULL; }
This function is just broken. You need to rethink it.
template<class DataType> // Empry the list out
void Stack<DataType>::makeEmpty() {
Node<DataType>* ptr = top;
while (top->next != NULL) {
One while loop will do you. Lists are linear, not square.
while (ptr->next != NULL) {
This statement has no effect; it does nothing. Your compiler should be warning about that, turn on warnings, or turn the warning level up.
ptr->next; }
delete ptr->next; } }
This is very broken too. You need to iterate over two lists, so you need two iterator variables. One iterator is the stuff you are copying and just needs to be bumped along as you read it. The other is mutating the current object and has slightly more book keeping.
template<class DataType> // Deep copy
inline void Stack<DataType>::deepCopy(const Stack<DataType>& original) {
Node<DataType>* copyptr = new Node<DataType>;
Node<DataType>* originalptr = top;
while (originalptr != NULL) {
originalptr = originalptr->next;
copyptr->next = new Node<DataType>;
copyptr->info = originalptr->info; } }
template<class DataType> // Copy Constructor
Stack<DataType>::Stack(const Stack<DataType>& element) {
deepCopy(element); }
template<class DataType> // Destructor
Stack<DataType>::~Stack() {
Note that makeEmpty does not delete your empty head node. This will leak a node.
makeEmpty(); }
template<class DataType> // Overload assignment operator
Stack<DataType>& Stack<DataType>::operator=(const Stack<DataType>&
element) {
if (this == &element) {
return *this; }
makeEmpty();
Again, your empty head node is causing pain here. Does deepCopy create the empty head node or not? Your use of it in your copy constructor seems to assume it does. Your use of it here seems to assume it does not. In fact, I think the problem is that makeEmpty does not delete your head node, if it did, both this function and your destructor would work properly.
deepCopy(element);
return *this; }

What you are seeing is a run-time error, not a build error. And your IDE reports a successful build, not your debugger. Your debugger is what allows you to trace through the program line-by-line and inspect the values of your variables.
Compare your code to the following.
template <class DataType>
struct Node {
DataType info;
Node<DataType>* next; };
template <class DataType>
class Stack {
public:
Stack();
void push(DataType elementToPush);
bool pop(DataType& poppedElement);
bool peek(DataType& topElement);
Stack(const Stack<DataType>& element);
~Stack();
Stack<DataType>& operator=(const Stack<DataType>& element);
bool isEmpty()const;
void makeEmpty();
private:
Node<DataType>* top;
inline void deepCopy(const Stack<DataType>& original); };
// Linked list stack implementation.
template<class DataType>
Stack<DataType>::Stack() {
// Head of the list. Not actually used for anything. Why is this here?
top = new Node<DataType>; }
// Remove the node at the front of the list and return the element
// Does not check for underflow.
template<class DataType>
bool Stack<DataType>::pop(DataType& poppedElement) {
Node<DataType>* ptr = top->next;
Node<DataType>* ptr2 = ptr->next;
top->next = ptr2;
poppedElement = ptr->info;
delete ptr;
return true; }
// Return the element at the front of the list without deleting it
template<class DataType>
bool Stack<DataType>::peek(DataType& topElement) {
if (top->next == NULL) {
return false; }
topElement = top->next->info;
return true; }
// Make a new node for the element and push it to the front of the list
template<class DataType>
void Stack<DataType>::push(DataType elementToPush) {
Node<DataType>* ptr2 = new Node<DataType>;
ptr2->info = elementToPush;
ptr2->next = top->next;
top->next = ptr2; }
// Check to see if the list is empty
template<class DataType>
bool Stack<DataType>::isEmpty()const {
return top->next == NULL; }
// Empty the list out
template<class DataType>
void Stack<DataType>::makeEmpty() {
while (top->next != NULL) {
Node<DataType>* ptr = top->next;
top->next = ptr->next;
delete ptr; } }
// Deep copy
template<class DataType>
inline void Stack<DataType>::deepCopy(const Stack<DataType>& original) {
Node<DataType>* origiter = original.top;
Node<DataType>* thisiter = top;
while (origiter->next != NULL) {
thisiter->next = new Node<DataType>(*(origiter->next));
origiter = origiter->next;
thisiter = thisiter->next; }
thisiter->next = NULL; }
// Copy Constructor
template<class DataType>
Stack<DataType>::Stack(const Stack<DataType>& element) {
deepCopy(element); }
// Destructor
template<class DataType>
Stack<DataType>::~Stack() {
// This leaks because the head node is still there.
makeEmpty(); }
// Overload assignment operator
template<class DataType>
Stack<DataType>& Stack<DataType>::operator=(const Stack<DataType>&
element) {
if (this == &element) {
return *this; }
makeEmpty();
deepCopy(element);
return *this; }

Related

Copy Constructor glitch during inserting elements into the stack

I've been given a Node and Stack class in my .h file. I have to implement the copy constructor, assignment operator and destructor and test them in a different test file. While testing the copy constructor after inserting 3 elements its displaying only one element. I don't know what's wrong; here's my .h file for your reference:
#ifndef _STACK_H
#define _STACK_H
#include <iostream>
#include <exception>
using std::ostream;
using std::cout;
using std::endl;
using std::range_error;
// Forward declarations
template <class T> class Stack;
template <class T> class Node;
template <class T> ostream& operator<<(ostream&, const Node<T>&);
// Node class for linked list
template <class T>
class Node {
friend Stack<T>;
public:
Node(T data = T(), Node<T>* next = nullptr) {
_data = data;
_next = next;
}
friend ostream& operator<< <T>(ostream& sout, const Node<T>& x);
private:
T _data;
Node* _next;
};
// Overloaded insertion operator. Must be overloaded for the template
// class T, or this won't work!
template <class T>
ostream& operator<<(ostream& sout, const Node<T>& x) {
sout << "Data: " << x._data;
return sout;
}
// Stack class. Linked-list implementation of a stack. Uses the Node
// class.
template <class T>
class Stack {
public:
// Constructor
Stack();
// Copy constructor, assignment operator, and destructor
// DO NOT IMPLEMENT HERE. SEE BELOW.
Stack(const Stack& rhs);
const Stack& operator=(const Stack& rhs);
~Stack();
void push(const T& data);
const T& top() const;
void pop();
bool empty() const; // Returns 'true' if stack is empty
void dump() const;
//Delete method used for destructor
void nullify();
private:
Node<T>* _head;
Node<T>* _temp1;
Node<T>* _temp2; //pointers
};
template <class T>
Stack<T>::Stack() {
_head = nullptr;
}
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) {
if (rhs._head != nullptr) {
_head = new Node<T>(rhs._head->_data);
_temp1 = _head->_next; //temp1 would be the next one after head
//_temp2 = _temp2->_next;
while (_temp2 != nullptr) {
_temp1 = new Node<T>(_temp2->_data);
_temp1 = _temp1->_next;
_temp2 = _temp2->_next; //temp2 should be the next node after temp1
}
}
else
_head = nullptr;
}
template <class T>
const Stack<T>& Stack<T>::operator=(const Stack<T>& rhs) {
if (this != &rhs) {
nullify();
if (rhs._head != nullptr) {
_head = new Node<T>(rhs._head->_data);
_temp1 = _head->_next; //temp1 would be the next one after head
//_temp2 = _temp2->_next;
while (_temp2 != nullptr) {
_temp1 = new Node<T>(_temp2->_data);
_temp1 = _temp1->_next;
_temp2 = _temp2->_next; //temp2 should be the next node after temp1
}
}
else
_head = nullptr;
}
return *this;
}
template <class T>
Stack<T>::~Stack() {
nullify();
}
template <class T>
void Stack<T>::nullify() {
while (!empty()) {
pop();
}
}
template <class T>
void Stack<T>::pop() {
if (empty()) {
throw range_error("Stack<T>::pop(): attempt to pop from an empty stack.");
}
Node<T>* tmpPtr = _head->_next;
delete _head;
_head = tmpPtr;
}
template <class T>
bool Stack<T>::empty() const {
return _head == nullptr;
}
template <class T>
void Stack<T>::push(const T& data) {
Node<T>* tmpPtr = new Node<T>(data);
tmpPtr->_next = _head;
_head = tmpPtr;
}
template <class T>
const T& Stack<T>::top() const {
if (empty()) {
throw range_error("Stack<T>::top(): attempt to read empty stack.");
}
return _head->_data;
}
template <class T>
void Stack<T>::dump() const {
Node<T>* nodePtr = _head;
while (nodePtr != nullptr) {
cout << nodePtr->_data << endl;
nodePtr = nodePtr->_next;
}
}
#endif
While pushing 34, 67, 92 it shows only 92 for the copy constructor during output. Here's the code for which I'm testing my .h code:
#include "stack.h"
#include <iostream>
using namespace std;
using std::cout;
using std::endl;
int main()
{
cout << "Testing default constructor\n";
Stack<int> intStack;
intStack.dump();
cout << "Stack is empty initially\n\n";
intStack.push(34);
intStack.push(67);
intStack.push(92);
cout << "Testing copy constructor after inserting 92, 67 & 34: \n";
Stack<int> test1(intStack);
//cout << "Dumping intStack into Test1 & displaying it: \n";
test1.dump();
cout << "\nTesting destructor: \n";
test1.nullify();
test1.dump();
cout << "Its empty\n\n";
Stack<int> test2;
test2.push(75);
test2.push(56);
test2.push(88);
test2.push(69);
cout << "Testing assignment operator after inserting 69, 88, 56 & 75: \n";
Stack<int> test3;
test3 = test2;
test3.dump();
cout << "\nTesting destructor: \n";
test2.nullify();
test2.dump();
cout << "Its empty\n\n";
return 0;
}
I'm still not used to C++ completely so sorry for any errors.
There are several things wrong with your Stack class.
First, the copy constructor doesn't initialize all the members, and neither does your default constructor. Those need to be fixed:
template <class T>
Stack<T>::Stack() : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {}
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr)
{
//...
}
Once this is done, the copy constructor can be easily implemented using your other existing function, Stack::push. Your implementation is way too complicated.
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {
Node<T>* temp = rhs._head;
while (temp)
{
push(temp->_data);
temp = temp->_next;
}
}
What is being done here? Simple -- all we are doing is taking the head of the passed-in Stack, and looping over the items calling Stack::push to add the data to the new Stack object. Since you have a push function already coded, you should be using it.
Second, note that we use a local temp variable. I doubt you need any of those _temp members in your class, but that is a different story.
Last, your assignment operator can easily be implemented, given you have a copy constructor and destructor for Stack:
template <class T>
const Stack<T>& Stack<T>::operator=(const Stack<T>& rhs) {
if (this != &rhs) {
Stack<T> temp = rhs;
std::swap(temp._head, _head);
std::swap(temp._temp1, _temp1);
std::swap(temp._temp2, _temp2);
}
return *this;
}
That technique uses copy / swap. All that is being done is to create a temporary from the passed-in Stack object, and just swap out the current contents with the temporary's contents. Then the temporary dies off with the old contents.
Given all of this, the class should work correctly. Whether it is 100% correct with all of the other functions, that again is a different issue.
Edit:
Here is a fix for the copy constructor. Note we still use existing functions to make the copy:
template <class T>
Stack<T>::Stack(const Stack<T>& rhs) : _head(nullptr), _temp1(nullptr), _temp2(nullptr) {
Node<T>* temp = rhs._head;
Stack<T> tempStack;
while (temp)
{
tempStack.push(temp->_data);
temp = temp->_next;
}
while (!tempStack.empty())
{
push(tempStack.top());
tempStack.pop();
}
}
This is not as efficient, but usually a stack data structure uses an underlying container such as vector where it is easy to reverse the underlying contents, and not based on a singly linked-list as you're using.

What i am making wrong with operator overloading?

I don't understand what is wrong when I overload operator +
(purpose of this is to join 2 stacks in one new) ...
it returns "sum" of but change values for those previous.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename T>
classStack
{
private:
struct Node
{
T data;
Node *next;
} *top;
std::size_t size;
public:
Stack();
~Stack();
void push(T data);
void pop(void);
size_t get_size(void);
const Stack& operator=(const Stack &stack_obj);
const Stack operator+(const Stack &stack_obj);
void show_all_stack(void);
};
template <typename T>
const Stack<T> Stack<T>::operator+(const Stack &stack_obj)
{
Stack stack;
Node *tmp;
if (!this->size && !stack_obj.size) {
return stack;
}
if (!stack_obj.size)
{
stack.size = size;
stack.top = top;
}
else if (!size)
{
stack.size = stack_obj.size;
stack.top = stack_obj.top;
}
else
{
stack.size = size + stack_obj.size;
stack.top = new Node;
stack.top = top;
tmp = stack.top;
while (tmp->next)
tmp = tmp->next;
tmp->next = new Node;
tmp->next = stack_obj.top;
}
return stack;
}
Default constructor
template <typename T>
Stack<T>::Stack(void): top(nullptr), size(0)
{
}
Destructor
template <typename T>
Stack<T>::~Stack(void)
{
Node *next;
if (!size)
std::cout << "Stack is empty!\n";
else
{
while (top != nullptr)
{
next = top->next;
delete top;
top = next;
}
top = nullptr;
}
}
Assignment operator
template <typename T>
const Stack<T>& Stack<T>::operator=(const Stack<T> &stack_obj)
{
Node *tmp;
Node *ptr;
Node *last;
Node *new_node;
if (&stack_obj != this)
{
while (top != nullptr)
{
tmp = top;
top = top->next;
delete tmp;
}
top = nullptr;
size = stack_obj.size;
ptr = stack_obj.top;
while (ptr)
{
new_node = new Node;
new_node->data = ptr->data;
new_node->next = nullptr;
if (!top)
{
top = new_node;
last = new_node;
}
else
{
last->next = new_node;
last = new_node;
}
ptr = ptr->next;
}
}
}
Before creating functions that return Stack<T> by value, or have functions that require copy semantics for Stack<T> (as in your operator +), you need to make sure that Stack<T> is safely copyable. Right now, you are lacking a copy constructor, thus your operator + would never work correctly, even if the function itself is bug-free.
You're missing this function:
Stack::Stack(const Stack<T>&)
The easiest way to implement the copy constructor is to take most of your code out of the assignment operator, and place that into the copy constructor. More or less, the code should look something like this (the code has not been compiled or tested -- it is there to illustrate the main point of this answer):
template <typename T>
Stack<T>::Stack<T>(const Stack<T> &stack_obj) : top(nullptr), size(0)
{
Node *tmp;
Node *ptr;
Node *last;
Node *new_node;
ptr = stack_obj.top;
while (ptr)
{
new_node = new Node;
new_node->data = ptr->data;
new_node->next = nullptr;
if (!top)
{
top = new_node;
last = new_node;
}
else
{
last->next = new_node;
last = new_node;
}
ptr = ptr->next;
}
}
You have already written a destructor that should work, so we won't get into that function, but a working destructor is required for the next step -- implementation of the assignment operator.
Now that you have a copy constructor and destructor, you can now write the assignment operator. The technique used here is the copy / swap idiom
#include <algorithm>
//...
template <typename T>
Stack<T>& Stack<T>::operator=(const Stack<T> &stack_obj)
{
if ( &stack_obj != this )
{
Stack<T> temp(stack_obj);
std::swap(top, temp.top);
std::swap(size, temp.size);
}
return *this;
}
Believe it or not, this works. The code that used to be here was moved to the copy constructor, and thus the assignment operator is going to take advantage of the copy constructor.
To explain briefly, the code creates a temporary Stack<T> object from the passed-in stack_obj (this is why you need a working copy constructor). Then all that is done is to swap out the this members with the temporary members. Last, the temp dies off with the old data (this is why the destructor needs to be working correctly).
Note that you need to swap all of the members, so if you add more members to the Stack<T> class, you need to swap them in the assignment operator.
Once you have the basic 3 functions (copy, assign, destroy) written correctly, then and only then should you write functions that return Stack<T> by value, or write functions that take a Stack<T> by value.
You may have other issues with operator + that lie outside the scope of what this answer is presenting to you, but the gist of it is that your class requires that it has correct copy semantics before implementing +.

Implementing assignment operator in linked list stack

I'm trying to do a deep copy assignment operator for a linked list stack. I think I've wrapped my head around what I need to do, but I can't quite get it.
Here is my code:
// Purpose: performs a deep copy of the data from rhs into this linked stack
// Parameters: rhs is linked stack to be copied
// Returns: *this
// Postconditions: this stack contains same data values (in the same order) as are in rhs; any memory previously used by this stack has been deallocated.
template <typename T>
const LinkedStack<T>& LinkedStack<T>::operator=(const LinkedStack<T>& rhs) {
while(rhs.m_head != NULL) {
m_head->m_data = rhs.m_head->m_data;
m_head->m_next = new Node<T>();
rhs.m_head = rhs.m_head->m_next;
m_head = m_head->m_next;
}
m_size = rhs.m_size;
}
So my thought process is to copy the data, make a new node, and then pop a node off of the rhs variable.
It currently errors on "rhs.m_head = rhs.m_head->m_next;" for "error: assignment of member 'LinkedStack::m_head' in read-only object". I'm not sure how to work around this since I'm being passed a constant reference.
Where am I going wrong?
The node header (templated):
template <class T>
class Node {
public:
T m_data; // Data to be stored
Node<T>* m_next; // Pointer to the next element in the list
Node() : m_next(NULL) {}
Node(const T& x, Node<T>* p) : m_data(x), m_next(p) {}
};
The linked stack header (templated):
template <class T>
class LinkedStack {
Node<T>* m_head; // Pointer to the top of the stack
int m_size; // The number of elements in the stack
public:
LinkedStack();
~LinkedStack();
const LinkedStack<T>& operator= (const LinkedStack<T>& rhs);
bool isEmpty() const;
const T& top() const throw (Oops);
void push(const T& x);
void pop();
void clear();
};
EDIT: Found the solution.
template <typename T>
const LinkedStack<T>& LinkedStack<T>::operator=(const LinkedStack<T>& rhs) {
clear();
Node<T>* temp = rhs.m_head;
m_head = new Node<T>();
Node<T>* c_head = m_head;
while(temp != NULL) {
m_head->m_data = temp->m_data;
temp = temp->m_next;
m_head->m_next = new Node<T>;
m_head = m_head->m_next;
}
m_head = c_head;
m_size = rhs.m_size;
return *this;
}
My major hangup was forgetting to reset m_head to the original head before I started using m_next.

Copy queue items into another class object

When I will display the items in a queue I use the while loop
while (!queue.isEmptyQueue())
{
cout << queue.front() << " ";
queue.deleteQueue();
}
The items will be gone because of the deleteQueue() function so I cannot display it again.
How can I create a copy of the queue?
I tried the code below but it gives me errors.
queue1 = queue;
while (!queue1.isEmptyQueue())
{
cout << queue1.front() << " ";
queue1.deleteQueue();
}
I am using linkedQueue.h
#include<assert.h>
template <class Type>
struct nodeType
{
Type info;
nodeType<Type> *link;
};
template <class Type>
class linkedQueueType //: public queueADT<Type>
{
public:
const linkedQueueType<Type>& operator=(const linkedQueueType<Type>&);
bool isEmptyQueue() const;
bool isFullQueue() const;
void initializeQueue();
Type front() const;
Type back() const;
void addQueue(const Type& queueElement);
void deleteQueue();
linkedQueueType();
linkedQueueType(const linkedQueueType<Type>& otherQueue);
~linkedQueueType();
private:
nodeType<Type> *queueFront;
nodeType<Type> *queueRear;
};
template <class Type>
bool linkedQueueType<Type>::isEmptyQueue() const
{
return(queueFront == NULL);
}
template <class Type>
bool linkedQueueType<Type>::isFullQueue() const
{
return false;
}
template <class Type>
void linkedQueueType<Type>::initializeQueue()
{
nodeType<Type> *temp;
while (queueFront!= NULL)
{
temp = queueFront;
queueFront = queueFront->link;
delete temp;
}
queueRear = NULL;
}
template <class Type>
void linkedQueueType<Type>::addQueue(const Type& newElement)
{
nodeType<Type> *newNode;
newNode = new nodeType<Type>;
newNode->info = newElement;
newNode->link = NULL;
if (queueFront == NULL)
{
queueFront = newNode;
queueRear = newNode;
}
else
{
queueRear->link = newNode;
queueRear = queueRear->link;
}
}
template <class Type>
Type linkedQueueType<Type>::front() const
{
assert(queueFront != NULL);
return queueFront->info;
}
template <class Type>
Type linkedQueueType<Type>::back() const
{
assert(queueRear!= NULL);
return queueRear->info;
}
template <class Type>
void linkedQueueType<Type>::deleteQueue()
{
nodeType<Type> *temp;
if (!isEmptyQueue())
{
temp = queueFront;
queueFront = queueFront->link;
delete temp;
if (queueFront == NULL)
queueRear = NULL;
}
else
cout << "Cannot remove from an empty queue" << endl;
}
template<class Type>
linkedQueueType<Type>::linkedQueueType()
{
queueFront = NULL;
queueRear = NULL;
}
template <class Type>
linkedQueueType<Type>::~linkedQueueType()
{
initializeQueue();
}
If what you want to do is copy the queue, then a copy constructor / assignment operator is what you should have, as Martin said.
But if what you want is for the items to still be there after you go through the queue, then what your queue is missing is a way to tell how many items are in the queue.
You can cout each item and then move it to the back of the queue, that number of times.
Either way, all of these are missing for it to be a good queue implementation.
Copy constructor, assignment operator, size function.
(And technically, a queue doesn't have functionality to access the back item. So I wouldn't call this a queue with missing functionality, I would call it a linked list with missing functionality.)
Your problem is that your linkedQueueType doesn't have an assignment operator so the compiler is giving you one which just copies the pointers. You need an assignment operator which clones the elements.

How do we include a struct in a c++ implementation file?

So I am trying to create my own implementation file which contains instructions for a Queue. I decided to use a linked list to implement the Queue class, meaning that I need to use my own Node struct. Unfortunately, I am stuck and don't know how to properly include this within the file.
This is what I have so far:
#include <string>
#ifndef NODE
template <class DataType>
struct Node
{
DataType data;
Node *next;
};
#endif
template <class DataType>
class Queue
{
public:
Queue();
bool isEmpty() const;
void push(const DataType& parameter);
bool peek(DataType& parameter) const;
bool pop(DataType& parameter);
void makeEmpty();
private:
Node<DataType>* front;
Node<DataType>* end;
};
template <class DataType>
Queue<DataType>::Queue()
: front(0), end(0)
{
}
template <class DataType>
bool Queue<DataType>::isEmpty() const {return 0 == front;}
template <class DataType>
void Queue<DataType>::push(const DataType& parameter)
{
Node<DataType>* node = new Node<DataType>;
node->data = parameter;
node->next = 0;
if (end) end->next = node;
else front = node;
end = node;
}
template <class DataType>
bool Queue<DataType>::peek(DataType& parameter) const
{
if (0 == front) return false; // failed
parameter = front->data;
return true; // success
}
template <class DataType>
bool Queue<DataType>::pop(DataType& parameter)
{
if (0 == front) return false; // failed
parameter = front->data;
Node<DataType>* p = front->next;
delete front;
front = p;
if (front == 0) end = 0;
return true; // success
}
template <class DataType>
void Queue<DataType>::makeEmpty()
{
end = 0;
Node<DataType>* p;
while (front)
{
p = front->next;
delete front;
front = p;
}
}
I'm not sure if I am enclosing the struct by the #ifndef correctly (i'm not even sure if this is the route I should be taking :/), should I be doing something similar to this or should I be doing something else with the code for the struct?
You can just drop the #ifdef/#endif entirely
This is a class template and it may occur many times in several tranlation units, as long as all the occurrences are identical (One Definition Rule)
Alternative
Since Node<> is purely a private concern, I'd make it a nested struct.
Here's a little demo making this more 'modern C++' style.
Edit Thanks to #R.MartinhoFernandes for showing a few more improvements and for reviewing this.
#include <memory>
template <typename T>
struct Queue {
Queue() : front(), end(/*nullptr*/) {}
// Copy-And-Swap idiom
// see http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap
// or http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
void swap(Queue& q) noexcept {
using std::swap;
swap(q.front, front);
swap(q.end, end);
}
Queue(Queue const& q) : front(), end() {
for(auto it=q.front.get(); it; it=it->next.get())
push(it->data);
}
Queue& operator=(Queue q) {
std::swap(*this, q);
return *this;
}
// end Copy-and-swap
// prevent stack overflows in ~Node if the list grows large (say >1k elements)
~Queue() { clear(); }
bool isEmpty() const {
return !front;
}
void push(T const& data) {
Ptr node(new Node(data));
if (end)
end->next = std::move(node);
else
front = std::move(node);
end = node.get();
}
bool peek(T& data) const {
if(front) data = front->data;
return front.get();
}
bool pop(T& data) {
if(!front) return false;
data = front->data;
front = std::move(front->next);
if(!front) end = nullptr;
return true;
}
void clear() {
end = nullptr;
while(front) front = std::move(front->next);
}
private:
struct Node;
typedef std::unique_ptr<struct Node> Ptr;
struct Node {
Node(T data) : data(std::move(data)), next() {}
T data;
Ptr next;
};
Ptr front;
Node* end;
};
#include <iostream>
int main(int argc, const char *argv[]) {
Queue<int> test;
test.push(1);
test.push(2);
test.push(3);
test.push(5);
test.clear();
test.push(32028);
test.push(10842);
test.push(1839);
test.push(23493);
test.push(9857);
int x;
test.peek(x);
while(test.pop(x)) {
std::cout << x << '\n';
}
}
Note: Perhaps the code in push has been golfed a bit too far, but hey, it shows you how modern C++ requires much less handholding (even without std::make_unique).
Note how I think Clang correctly handles the following version (i.e. with implicit std::move):
void push(const DataType& parameter) {
end = ((end? end->next : front) = Ptr(new Node(parameter))).get();
}
I'm not quite sure why gcc rejects it.