1. No.
3. Stack::~Stack() is incorrect. In some cases it leaks memory, in other cases it deletes the same pointer twice. It only behaves correctly if Stack::size == 0.
you are going to need to delete each pointer that was allocated. You should start from the top of the stack and work towards the bottom deleting everything.
#include <iostream>
template <class T>
struct Node
{
Node *next;
T value;
};
template <class T>
class Stack
{
public:
Stack() : top(new Node<T>), size(0)
{
top->next = nullptr;
//value is undefined because there is nothing on the stack
}
~Stack()
{
while(top != nullptr)
{
Node<T> *next = top->next;
delete top;
top = next;
}
}
std::size_t length(void) const {return size;}
void push(T value) //pushes item onto stack
{
Node<T> *temp = new Node<T>{top, value};
top = temp;
++size;
}
T pop(void) //removes top item and returns it
{
if(size < 1)
{
throw("Error - Can't pop an empty stack.");
}
T temp = top->value;
Node<T> *next = top->next;
delete top;
top = next;
--size;
return temp;
}
T peek(void) //returns top item
{
if(size < 1)
throw("Error - The stack is empty.");
return top->value;
}
private:
Node<T> *top;
std::size_t size;
};
int main()
{
Stack<int> test;
std::cout << "Size: " << test.length() << std::endl; //0
for(int i = 0; i < 5; ++i)
{
test.push(i);
std::cout << "Added " << i << " to the stack." << std::endl;
}
std::cout << "Size: " << test.length() << std::endl; //5
try
{
std::cout << "Removing " << test.pop() << " from the stack" << std::endl; //4
}
catch(charconst *e)
{
std::cout << e << std::endl;
}
try
{
std::cout << "Top: " << test.peek() << std::endl; //3
}
catch(charconst *e)
{
std::cout << e << std::endl;
}
int size = test.length();
for(int i = 0; i <= size; ++i) //purposely try and delete one more than possible.
{
std::cout << "Size: " << test.length() << std::endl; //5
try
{
std::cout << "Removing " << test.pop() << " from the stack" << std::endl; //4
}
catch(charconst *e)
{
std::cout << e << std::endl;
}
try
{
std::cout << "Top: " << test.peek() << std::endl; //3
}
catch(charconst *e)
{
std::cout << e << std::endl;
}
}
return 0;
}
Size: 0
Added 0 to the stack.
Added 1 to the stack.
Added 2 to the stack.
Added 3 to the stack.
Added 4 to the stack.
Size: 5
Removing 4 from the stack
Top: 3
Size: 4
Removing 3 from the stack
Top: 2
Size: 3
Removing 2 from the stack
Top: 1
Size: 2
Removing 1 from the stack
Top: 0
Size: 1
Removing 0 from the stack
Error - The stack is empty.
Size: 0
Error - Can't pop an empty stack.
Error - The stack is empty.
Hopefully it will help you understand it easier.
If you have learned about smart pointers also I would suggest using a std::unique_ptr<T> to prevent any possible memory leaks.
*Slight improvement (forgot to check if the size was > 0 before popping :P) Also removed the setting value equal to 0 on the "out of bounds" value.