#include using namespace std; // my own version of shared_ptr; template struct Weak; template class Rc { private: T* ptr{nullptr}; int* refcount{nullptr}; Rc(T* p) { ptr = p; refcount = new int(1); } void dealloc() { if ((*refcount) < 1) { delete ptr; delete refcount; ptr = nullptr; refcount = nullptr; } } public: Rc() {} ~Rc() { if (refcount) { (*refcount)--; dealloc(); } }// destructor template static Rc New(Args&&... args) { return Rc(new T(std::forward(args)...)); } T& operator *() { return *ptr; } T* operator ->() { return ptr; } // copy semantics Rc(const Rc& other) { ptr = other.ptr; refcount = other.refcount; if (refcount) (*refcount)++; } const Rc& operator =(const Rc& other) { if (refcount && ptr!=other.ptr) { (*refcount)--; dealloc(); } if (ptr!=other.ptr && other.refcount) (*other.refcount)++; ptr = other.ptr; refcount = other.refcount; return other; } // move semantics Rc(Rc&& other) { ptr = other.ptr; refcount = other.refcount; other.refcount = nullptr; other.ptr = nullptr; } void operator =(Rc&& other) { if (refcount && ptr != other.ptr) { (*refcount)--; dealloc(); } ptr = other.ptr; refcount = other.refcount; other.refcount = nullptr; other.ptr = nullptr; } int use_count() { if (refcount) return *refcount; else return 0; } friend struct Weak; }; // also need weak. template struct Weak { private: T* ptr{nullptr}; int* refcount{nullptr}; public: Weak() {} Weak(const Rc& other) { ptr = other.ptr; refcount = other.refcount; } void operator =(const Rc& other) { ptr = other.ptr; refcount = other.refcount; } Rc lock() { Rc temprc; temprc.ptr = ptr; temprc.refcount = refcount; if (refcount) (*refcount)++; return temprc; } bool expired() { if (!ptr || !refcount) return true; else return (*refcount)<1; } int use_count() { if (!ptr || !refcount) return 0; else return *refcount; } }; // flaw: Rc* refed could get deallocated, leaving a dangling raw pointer. struct bad_share { int A[10]; Rc other; }; void leaktest() { auto a = Rc::New(); auto b = Rc::New(); a->other = b; b->other = a; } struct fixed_share { int A[10]; Weak other; }; void noleaktest() { auto a = Rc::New(); auto b = Rc::New(); a->other = b; b->other = a; } void test() { Rc a = Rc::New(4); Rc b = Rc::New(5); a = b; Rc c = Rc::New(6); c = move(b); Weak w = a; Rc locked = w.lock(); cout << a.use_count() << endl; cout << b.use_count() << endl; cout << c.use_count() << endl; } int main() { //while (1) test(); test(); while (1) noleaktest(); return 0; }