Please review my Stack using linked list:template<class T>struct Node {    T item;    Node* next;    Node(T t = {}, Node* link = nullptr) :item{t}, next{link} { }    ~Node() { delete next; }};template<class T>class Stack {public:    int size() const { return n; }    bool empty() const { return n == 0; }    void push(const T&);    T pop();    T peek();private:    Node<T>* first;    std::size_t n;};template<class T>void Stack<T>::push(const T& t) {    Node<T>* old{first};    first = new Node<T>{t,old};    ++n;}template<class T>T Stack<T>::pop() {    if (empty()) {        throw std::out_of_range(underflow);    }    auto t = first->item;    first = first->next;    --n;    return t;}template<class T>T Stack<T>::peek() {    if (empty()) {        throw std::out_of_range(underflow);    }    return first->item;}A few notes:I would like to experiment to try to avoid allocating in the heap, but I really can't because I don't know how to keep the newly created and added node in push() alive.Is it correct to use std::size_t when tracking the size of the stack?I thought that since my Stack class acts like a handle to nodes, I thought I should write my own copy and move operations so I can avoid member-wise copying, but something very funny happens when I tested my Stack:int main() {    Stack<std::string> x{};    x.push(str);    x.push(tring);    x.push(string);    Stack<std::string> y = x;    y.pop();    std::cout << x.peek() << '\n';    y.pop();    std::cout << x.peek() << '\n';    y.pop();    std::cout << x.peek() << '\n';    y.push(nox);    std::cout << x.peek() << '\n';    std::cout << x.size() << '\n';    std::cout << y.size() << '\n';}When x.peek() is called the result is always string, x.size() is 3 and y.size() is 1. It seems the default copy operation works correctly. I thought it shouldn't because first is a pointer so they should refer to the same elements.So I did not write a copy and move operation because it seems the default operations work correctly but I really don't know why and how. Can anyone explain why?How can I make this code better?
Simple stack implementation using linked list
c++;c++11;stack
I see some things that you might want to use to improve your code.Use appropriate #include filesThe implementation requires #include <stdexcept> so that should part of the template.Eliminate unneeded variablesThe push function doesn't really need any temporary variables:template<class T>void Stack<T>::push(const T& t) {    first = new Node<T>{t,first};    ++n;}Create a default constructor for StackAn instance of Stack is not necessarily initialized to any particular values when it's created.  To address this, you should implement a default constructor.Stack() : first{nullptr}, n{0} {}Match new with deleteIf you allocate memory using new, you must also free it using delete or your program will leak memory.  Since you use new in push(), you should use delete in pop():template<class T>T Stack<T>::pop() {    if (empty()) {        throw std::out_of_range(underflow);    }    Node<T>* oldnode = first;    T t = first->item;    first = first->next;    --n;    delete oldnode;    return t;}Create a copy constructor if you need oneThe compiler will create a default copy constructor which does a shallow copy, but this won't work for data structures, like yours, which use pointers.  Instead, if you really want to create a new Stack from an existing one, you'll need to creat your own copy constructor:template<class T>Stack<T>::Stack(const Stack<T> &s) : first(nullptr), n(0) {    for (auto t=s.first; t; t = t->next)        push(t->item);}The default-constructed operator= will now use this copy constructor.Create a destructor if you need oneFor similar reasons, you need have a delete for Stack and not for Node.  The one for Stack could be like this:template<class T>Stack<T>::~Stack() {    while (!empty())        pop();}Use const where possibleThe peek() function doesn't (and shouldn't) alter the underlying Stack so it should be declared const.  Consider using referencesWhile this code works (with the adjustments listed above), ther is still some room for improvement.  First, things inserted into the stack are copied rather than moved there.  Also things that are popped from the stack are also copied rather than moved.  This means that there are many more constructor and destructor calls made than are strictly necessary.To see how this works, here's a class that contains a string, but includes instrumentation so we can see what's happening:class MyString {public:    MyString() : str(), id(serial++) { std::cout << creating empty string  << id << \n; }    MyString(const char *msg) : str(msg), id(serial++) {         std::cout << creating string \ << str << \  << id << \n; }    MyString(const MyString &s) : str(s.str), id(serial++) {         std::cout << copying string \ << str << \  << id << \n; }    MyString(MyString &&s) : str(), id(serial++) {         std::swap(str, s.str);        std::cout << moving string \ << str << \  << id << \n; }    ~MyString() { std::cout << destroying string  << id << \n; }    friend std::ostream &operator<<(std::ostream &out, const MyString &m) {        return out << m.str;    }private:    static unsigned serial;    std::string str;    unsigned id;};unsigned MyString::serial = 0;Now we specialize your templated stack and try it out:int main() {    Stack<MyString> x{};    x.push(one);    x.push(two);    x.push(three);    std::cout << x.peek() << '\n';}Output from this program (with the other fixes included):creating string one 0copying string one 1copying string one 2destroying string 1destroying string 0creating string two 3copying string two 4copying string two 5destroying string 4destroying string 3creating string three 6copying string three 7copying string three 8destroying string 7destroying string 6copying string three 9threedestroying string 9copying string three 10destroying string 8destroying string 10copying string two 11destroying string 5destroying string 11copying string one 12destroying string 2destroying string 12As you can see, even though we've only got three items on the stack, we've created and destroyed 13 objects.  By making only a single small change to the Node constructor, we can reduce that to 10:Node(const T &t, Node* link) :item{t}, next{link} {}More savings could be realized by not using pop in the destructor since pop creates a copy of T to return:template<class T>Stack<T>::~Stack() {    if (first) {        for (Node<T> *n = first->next; n; n = first->next) {            delete first;            first = n;        }        delete first;    }}Consider using smart pointersUsing something like a std::unique_ptr would free you (pun intended) from having to manage the mechanics of new and delete explicitly.