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));
}