#include <cassert>
#include <iostream>

class IntegerMember {
   public:
      IntegerMember(int member, IntegerMember* next) :
	 member(member), next(next) {
      }
      IntegerMember(const IntegerMember& other) :
	 member(other.member),
	 next(
	    other.next?
	       new IntegerMember(*other.next)
	    :
	       nullptr
	 ) {
      }
      ~IntegerMember() {
	 delete next;
      }
      IntegerMember& operator=(const IntegerMember& other) {
	 delete next;
	 member = other.member;
	 if (other.next) {
	    next = new IntegerMember(*other.next);
	 } else {
	    next = nullptr;
	 }
	 return *this;
      }
      int member;
      IntegerMember* next;
};

class IntegerStack {
   public:
      IntegerStack() : top(nullptr) {
      }
      IntegerStack(const IntegerStack& other) :
	 top(
	    other.top?
	       new IntegerMember(*other.top)
	    :
	       nullptr
	 ) {
      }
      ~IntegerStack() {
	 delete top;
      }
      IntegerStack& operator=(const IntegerStack& other) {
	 delete top;
	 if (other.top) {
	    top = new IntegerMember(*other.top);
	 } else {
	    top = nullptr;
	 }
	 return *this;
      }
      void push(int member) {
	 top = new IntegerMember(member, top);
      }
      bool empty() {
	 return top == nullptr;
      }
      int pop() {
	 assert(top != nullptr);
	 int member = top->member;
	 IntegerMember* old = top;
	 top = top->next;
	 old->next = nullptr;
	 delete old;
	 return member;
      }
   private:
      IntegerMember* top;
};

void print(const char* name, IntegerStack& s) {
   std::cout << name << ":";
   while (!s.empty()) {
      std::cout << " " << s.pop();
   }
   std::cout << std::endl;
}

int main() {
   IntegerStack a; a.push(1); a.push(2); a.push(3);
   {
      IntegerStack b{a};
      print("b", b);
   }
   {
      IntegerStack c; c = a;
      print("c", c);
   }
   print("a", a);
}
