#include #include using namespace std; // my implementation of unique_ptr, without specialization for T[] template struct Box { private: T* ptr{nullptr}; Box(T* n) : ptr{n} {} // private constructor public: Box() {} ~Box() { if (ptr) delete ptr; } T& operator *() { return *ptr; } T* operator ->() { return ptr; } operator bool() { return ptr != nullptr; } // if (box1) .. // move semantics template Box(Box&& other) { ptr = static_cast(other.ptr); other.ptr = nullptr; } template Box& operator =(Box&& other) { if (this == (Box*)&other) return *this; if (ptr) delete ptr; ptr = static_cast(other.ptr); other.ptr = nullptr; return *this; } // delete copy semantics manually Box(const Box& other) = delete; const Box& operator =(const Box& other) = delete; template static Box New(Args&&... args) noexcept { return Box(new T(forward(args)...)); } template friend Box make_box(Args&&... args) noexcept; template friend struct Box; }; template Box make_box(Args&&... args) noexcept { return Box(new T(forward(args)...)); } struct A { //Box n{make_box(1)}; unique_ptr n{make_unique(1)}; virtual int f() = 0; virtual ~A() {} //= default; }; struct B:A { //Box m{make_box(2)}; unique_ptr m{make_unique(2)}; // default destructor overrides virtual destructor. int f() override { return 1; } }; struct B2:B { unique_ptr z{make_unique(3)}; // default destructor overrides virtual destructor. int f() override { return 1; } }; struct C:A { int f() override { return 2; } }; struct D { Box n; }; void willitleak() { //Box b = Box::New(); Box b2 = Box::New(); } int testbox() { Box a = Box::New(4); Box b = Box::New(5); //a = b; //move(b); a = move(b); Box c = make_box(6); cout << *a << endl; cout << *c << endl; Box n = Box::New(); Box m = Box::New(); //n = m; n = move(m); D d1; D d2 = move(d1); while (1) willitleak(); return 0; } ////////////////////////// shared_ptr and weak_ptr ////////////////// template struct Rc { // "reference counter" private: T* ptr{nullptr}; unsigned int* refcount{nullptr}; int* weakcount{nullptr}; // make sure weak pointers properly handled Rc(T* n) : ptr{n} { refcount = new unsigned int(1); weakcount = new int(0); } void deallocate() { (*refcount)--; if (*refcount==0) { delete ptr; delete refcount; if (*weakcount == 0) delete weakcount; else *weakcount = -1 * *weakcount; // indicates weak ptrs now invalid } } public: Rc() {} ~Rc() { if (refcount) deallocate(); } void drop() { if (refcount) { deallocate(); refcount = nullptr; ptr = nullptr; weakcount = nullptr; } } T& operator *() { return *ptr; } T* operator ->() { return ptr; } template Rc(Rc& other) { ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; if (refcount) (*refcount)++; } template Rc& operator =(Rc& other) { if (this == (Rc*)&other) return other; if (refcount) deallocate(); ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; if (refcount) (*refcount)++; return other; } template Rc(Rc&& other) { ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; other.ptr = nullptr; other.refcount = nullptr; other.weakcount = nullptr; } template void operator =(Rc&& other) { if (this == (Rc*)&other) return; if (refcount) deallocate(); ptr = static_cast(other.ptr); refcount = other.refcount; weakcount = other.weakcount; other.ptr = nullptr; other.refcount = nullptr; other.weakcount = nullptr; } unsigned int use_count() { if (refcount) return *refcount; else return 0; } template static Rc New(Args&&... args) { return Rc(new T(forward(args)...)); } template friend struct Weak; template friend struct Rc; }; // Rc template struct Weak { private: T* ptr{nullptr}; unsigned int* refcount{nullptr}; int* weakcount{nullptr}; void deallocate() { if (weakcount) { if (*weakcount>0) (*weakcount)--; else if (*weakcount < -1) (*weakcount)++; else delete weakcount; } } public: Weak() {} ~Weak() { deallocate(); } void drop() { deallocate(); weakcount=nullptr; } Weak(Rc& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Rc"; ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } void operator =(Rc& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Rc"; deallocate(); ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } Weak(const Weak& other) { if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Weak pointer"; ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; } const Weak& operator =(const Weak& other) { if (this == &other) return other; if (!other.weakcount || *other.weakcount<0) throw "Assignment of Weak pointer to invalidated Weak pointer"; deallocate(); ptr = other.ptr; refcount = other.refcount; weakcount = other.weakcount; (*weakcount)++; return other; } Rc lock() { if (weakcount && *weakcount>0) { Rc rc; rc.ptr = ptr; rc.refcount = refcount; rc.weakcount = weakcount; (*refcount)++; return rc; } else throw "lock on invalidated Rc"; } int weak_count() { if (weakcount) return *weakcount; else return 0; } }; void doesitleak() { Rc a = Rc::New(3); Weak w1 = a; Weak w2 = a; Rc b = move(a); //b.drop(); //cout << w2.weak_count() << endl; //w2.drop(); //cout << w1.weak_count() << endl; //w1.drop(); //*w1.lock() = 5; //cout << *w2.lock() << endl; Weak w3 = w2; Rc n; n = Rc::New(); } int main() { doesitleak(); //while (true) doesitleak(); return 0; }