Smart pointer – principle and imitation of shared_ptr

The principle and imitation of shared_ptr

  • A shared pointer allows multiple pointers to point to the same data because it uses a reference count. Every time an additional pointer points to this data, the reference technology increases by one. Every time a pointer is destroyed, the reference technology decreases by one. If the reference count is 0, delete this data.
  • But shared pointers cannot assign the same raw pointer to multiple smart pointers, because this will be two independent shared pointers, and they will be counted separately, which means that they will be released repeatedly.
  • First version without counter design:
template<typename T>
class MyShared_ptr {<!-- -->
private:
    //internal pointer
    T* m_ptr;
    //counter
    long* m_count;
public:
    //Construct a shared pointer with a raw pointer, the default is nullptr
    //Prohibit implicit construction
    explicit MyShared_ptr(T* ptr = nullptr) : m_ptr(ptr) {<!-- -->
        //Counter initialized to 1
        m_count = new long(1);
    }
    //Construct a shared pointer with MyUnique_ptr rvalue
    MyShared_ptr(MyUnique_ptr<T> & amp; & amp; src) {<!-- -->
        //Destroy the exclusive pointer and take out the raw pointer
        m_ptr = src.release();
        //Counter initialized to 1
        m_count = new long(1);
    }
    //copy constructor
    MyShared_ptr(const MyShared_ptr & amp; src) {<!-- -->
        m_ptr = src.m_ptr;
        //Copy counter pointer
        m_count = src.m_count;
        //counter plus one
        (*m_count) + + ;
    }
    //Copy assignment
    MyShared_ptr & amp; operator=(const MyShared_ptr & amp; src) {<!-- -->
        if ( & amp;src == this) return *this;
        //If it is not empty, call the destructor first
        if (m_ptr != nullptr) {<!-- -->
            this->~MyShared_ptr();
        }
        m_ptr = src.m_ptr;
        m_count = src.m_count;
        (*m_count) + + ;
        return *this;
    }
    //Copy assignment using MyUnique_ptr rvalue
    MyShared_ptr & amp; operator=(const MyUnique_ptr<T> & amp; & amp; src) {<!-- -->
        if (m_ptr != nullptr) {<!-- -->
            this->~MyShared_ptr();
        }
        //Destroy the exclusive pointer and take out the raw pointer
        m_ptr = src.release();
        m_count = new long(1);
        return *this;
    }
    //destructor
    ~MyShared_ptr() {<!-- -->
        //Counter decreases by one
        (*m_count)--;
        //If the counter is 0, release the pointer space and counter space
        if (0 == *m_count) {<!-- -->
            delete m_ptr;
            delete m_count;
            m_ptr = nullptr;
            m_count = nullptr;
        }
    }
    //Get the internal pointer address
    T* get() {<!-- -->
        return m_ptr;
    }
    //reset pointer
    void reset(T* ptr = nullptr) {<!-- -->
        //Call the destructor first
        this->~MyShared_ptr();
        m_ptr = ptr;
        m_count = new long(1);
    }
    //Return the current reference count
    long use_count() {<!-- -->
        return *m_count;
    }
    //conversion function bool
    operator bool() const {<!-- -->
        return m_ptr != nullptr;
    }
    //Is the current shared pointer unique?
    bool unique() {<!-- -->
        if (1 == *m_count) return true;
        else return false;
    }
    //Member function exchanges pointers and counters
    void swap(MyShared_ptr<T> & amp; src) {<!-- -->
        T* temp_ptr;
        long* temp_count;
        temp_ptr = src.m_ptr;
        temp_count = src.m_count;
        src.m_ptr = m_ptr;
        src.m_count = m_count;
        m_ptr = temp_ptr;
        m_count = temp_count;
    }
    //Reload*
    T & amp; operator*() const {<!-- -->
        return *m_ptr;
    }
    //Reload->
    T* operator->() const {<!-- -->
        return (& amp;**this);
    }
};
//Global function, with rvalue reference make_MyShared
template<class T>
MyShared_ptr<T> make_MyShared(MyShared_ptr<T> & amp; & amp; src) {<!-- -->
    return MyShared_ptr<T>(forward<MyShared_ptr<T>>(src));
}
  • Version with counter design
//Counter design
template<typename T>
class MyCount {<!-- -->
private:
    //Storage reference count and weak pointer count separately
    long use_count;
    long weak_count;
public:
    //Initialization of counter
    MyCount(long u,long w) : use_count(u), weak_count(w) {<!-- -->}
    //Weak pointer counting + +
    void Increase_weak_count() {<!-- -->
         + + weak_count;
    }
    //Weak pointer count--
    void Decrease_weak_count() {<!-- -->
        --weak_count;
    }
    //Reference counting + +
    void Increase_use_count() {<!-- -->
         + + use_count;
    }
    //reference count--
    void Decrease_use_count() {<!-- -->
        --use_count;
    }
    //Get reference count
    long get_use_count() {<!-- -->
        return use_count;
    }
    //Release the memory of the passed object
    void DestroyPtr(T* ptr) {<!-- -->
        delete ptr;
    }
    //If there is no weak pointer, release the counter
    void DestroyThis() {<!-- -->
        if(0 == weak_count)
            delete this;
    }
};

template<typename T>
class MyShared_ptr {<!-- -->
private:
    //internal pointer
    T* m_ptr;
    //Counter pointer
    MyCount<T>* m_count;
public:
    //Construct shared pointer with raw pointer
    explicit MyShared_ptr(T* ptr = nullptr) : m_ptr(ptr) {<!-- -->
        //Initialize the counter to reference 1 and weak pointer 0
        m_count = new MyCount<T>(1,0);
    }
    //Construct a shared pointer from an exclusive pointer
    MyShared_ptr(MyUnique_ptr<T> & amp; & amp; src) {<!-- -->
        //Destroy the exclusive pointer and take out the raw pointer
        m_ptr = src.release();
        //Initialize the counter to reference 1 and weak pointer 0
        m_count = new MyCount<T>(1, 0);
    }
    //copy construction
    MyShared_ptr(const MyShared_ptr & amp; src) {<!-- -->
        m_ptr = src.m_ptr;
        m_count = src.m_count;
        //Reference counting + +
        m_count->Increase_use_count();
    }
    //Copy assignment
    MyShared_ptr & amp; operator=(const MyShared_ptr & amp; src) {<!-- -->
        if ( & amp;src == this) return *this;
        if (m_ptr != nullptr) {<!-- -->
            this->~MyShared_ptr();
        }
        m_ptr = src.m_ptr;
        m_count = src.m_count;
        //Reference counting + +
        m_count->Increase_use_count();
        return *this;
    }
    //Copy exclusive pointer assignment
    MyShared_ptr & amp; operator=(const MyUnique_ptr<T> & amp; & amp; src) {<!-- -->
        if (m_ptr != nullptr) {<!-- -->
            this->~MyShared_ptr();
        }
        m_ptr = src.release();
        m_count = new MyCount<T>(1, 0);
        return *this;
    }
    //destructor
    ~MyShared_ptr() {<!-- -->
        //reference count--
        m_count->Decrease_use_count();
        //If the reference count is zero
        if (0 == m_count->get_use_count()) {<!-- -->
            //Release pointer
            m_count->DestroyPtr(m_ptr);
            //Destroy the counter (the counter internally determines whether there is a weak pointer)
            m_count->DestroyThis();
            m_ptr = nullptr;
            m_count = nullptr;
        }
    }
    //Get the internal pointer address
    T* get() {<!-- -->
        return m_ptr;
    }
    //Reset shared pointer to new pointer
    void reset(T* ptr = nullptr) {<!-- -->
        this->~MyShared_ptr();
        m_ptr = ptr;
        m_count = new MyCount<T>(1, 0);
    }
    //return reference count
    long use_count() {<!-- -->
        return m_count->get_use_count();
    }
    //conversion function
    operator bool() const {<!-- -->
        return m_ptr != nullptr;
    }
    //Is it unique?
    bool unique() {<!-- -->
        if (1 == m_count->get_use_count()) return true;
        else return false;
    }
    //Exchange pointers and counters
    void swap(MyShared_ptr<T> & amp; src) {<!-- -->
        T* temp_ptr;
        MyCount<T>* temp_count;
        temp_ptr = src.m_ptr;
        temp_count = src.m_count;
        src.m_ptr = m_ptr;
        src.m_count = m_count;
        m_ptr = temp_ptr;
        m_count = temp_count;
    }
    //Reload*
    T & amp; operator*() const {<!-- -->
        return *m_ptr;
    }
    //Reload->
    T* operator->() const {<!-- -->
        return (& amp;**this);
    }
    //Set the weak pointer class as a friend class
    template<typename T>
    friend class MyWeak_ptr;
};

//Global function, with rvalue reference make_MyShared
template<class T>
MyShared_ptr<T> make_MyShared(MyShared_ptr<T> & amp; & amp; src) {<!-- -->
    return MyShared_ptr<T>(forward<MyShared_ptr<T>>(src));
}