#include <iostream>

template <typename T>
class shared_ptr {
  T *ptr;
  int *cnt;
public:
  shared_ptr(T *ptr) : ptr(ptr), cnt(new int(1)) {}
  shared_ptr(shared_ptr const& o) : ptr(o.ptr), cnt(o.cnt) { ++*cnt; }
  ~shared_ptr() { if (!--*cnt) { delete ptr; delete cnt; } }

  friend inline void swap(shared_ptr& lhs, shared_ptr& rhs)
  { std::swap(lhs.ptr, rhs.ptr); std::swap(lhs.cnt, rhs.cnt); }
  shared_ptr& operator=(shared_ptr rhs) { swap(*this, rhs); return *this; }
};

struct test {
  const char *c;
  test(const char *c):c(c){ std::cout << "construct " << c << '\n'; }
  ~test(){ std::cout << "destruct " << c << '\n'; }
};

int main()
{
  shared_ptr<test> t(new test("A"));
  {
    shared_ptr<test> v(new test("B"));
    {
      shared_ptr<test> s(new test("C"));
      shared_ptr<test> u(new test("D"));
      t = s;
    }
  }
}
