I am a mathematician attempting to become proficient with C++. At the moment I am learning about data structures. I am now writing a stack data structure using linked list from scratch.
I have tested my class that I wrote and everything seems to be working fine but I want to see if there are any bugs or some areas of the code I could improve on.
Here is the class:
#ifndef Stack_h
#define Stack_h
template <class T>
class Stack {
private:
struct Node {
T data;
Node* next;
};
Node* top;
public:
// Constructors
Stack() : top(nullptr){} // empty constructor
Stack(Stack const& value); // copy constructor
Stack<T>(Stack<T>&& move) noexcept; // move constuctor
Stack<T>& operator=(Stack&& move) noexcept; // move assignment operator
~Stack(); // destructor
// Overload operators
Stack& operator=(Stack const& rhs);
friend std::ostream& operator<<(std::ostream& str, Stack<T> const& data) {
data.show(str);
return str;
}
// Member functions
void swap(Stack& other) noexcept;
bool isEmpty();
int getSize();
void push(const T& theData);
void push(T&& theData);
void pop();
void show(std::ostream &str) const;
};
template <class T>
Stack<T>::Stack(Stack const& value) : top(nullptr) {
for(Node* loop = value->data; loop != nullptr; loop = loop->next) {
push(loop->data);
}
}
template <class T>
Stack<T>::Stack(Stack<T>&& move) noexcept : top(nullptr) {
move.swap(*this);
}
template <class T>
Stack<T>& Stack<T>::operator=(Stack<T> &&move) noexcept {
move.swap(*this);
return *this;
}
template <class T>
Stack<T>::~Stack() {
while(top != nullptr) {
pop();
}
}
template <class T>
Stack<T>& Stack<T>::operator=(Stack const& rhs) {
Stack copy(rhs);
swap(copy);
return *this;
}
template <class T>
void Stack<T>::swap(Stack<T> &other) noexcept {
using std::swap;
swap(top,other.top);
}
template <class T>
bool Stack<T>::isEmpty() {
if(top == nullptr) {
return true;
}
else {
return false;
}
}
template <class T>
int Stack<T>::getSize() {
int size = 0;
Node* current = top;
while(current != nullptr) {
size++;
current = current->next;
}
return size;
}
template <class T>
void Stack<T>::push(const T &theData) {
Node* newNode = new Node;
newNode->data = theData;
newNode->next = nullptr;
if(top != nullptr) {
newNode->next = top;
}
top = newNode;
}
template <class T>
void Stack<T>::push(T&& theData) {
Node* newNode = new Node;
newNode->data = std::move(theData);
newNode->next = nullptr;
if(top != nullptr) {
newNode->next = top;
}
top = newNode;
}
template <class T>
void Stack<T>::pop() {
Node* temp;
if(top == nullptr) {
throw std::invalid_argument("The list is already empty, nothing to pop.");
}
temp = top;
top = top->next;
delete temp;
}
template <class T>
void Stack<T>::show(std::ostream &str) const {
for(Node* loop = top; loop != nullptr; loop = loop->next) {
str << loop->data << "\t";
}
str << "\n";
}
#endif /* Stack_h */
Here is the main.cpp file that tests the class:
#include <iostream>
#include "Stack.h"
int main(int argc, const char * argv[]) {
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Stack Using Linked List //////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
Stack<int> obj;
obj.push(2);
obj.push(4);
obj.push(6);
obj.push(8);
obj.push(10);
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Displaying Stack Contents---------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Pop Stack Element -------------------";
std::cout<<"\n--------------------------------------------------\n";
obj.pop();
std::cout << obj << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Get the size of stack -------------------";
std::cout<<"\n--------------------------------------------------\n";
std::cout << obj.getSize() << std::endl;
std::cout<<"\n--------------------------------------------------\n";
std::cout<<"---------------Re-Add Poped Element---------------";
std::cout<<"\n--------------------------------------------------\n";
obj.push(10);
std::cout << obj << std::endl;
return 0;
}
Stack operator=(const Stack&)
andStack<T>::swap
are missing. Also there is no way to access any data in the stack from outside (not even the top!) other than outputting them to a stream. Is this intended? \$\endgroup\$top
should return the topmost element, so avoid
return type would not be suitable. However, you might want to think about whether you want to returnT
by value or by reference. \$\endgroup\$show
function. I'm sure it helped you with debugging, but the user should not be able to see any elements in a stack except for the top element. The way to print the elements in a stack is by repeatedly printing the top element and popping the stack until the stack is empty. This can be done by the user. Otherwise, it's just a linked list, where "push" and "pop" mean "insert at the front," and "delete from the front," respectively. The fact that the stack is implemented using a linked list should be hidden completely from the user. \$\endgroup\$