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>::swapare 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\$topshould return the topmost element, so avoidreturn type would not be suitable. However, you might want to think about whether you want to returnTby value or by reference. \$\endgroup\$showfunction. 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\$