shared_ptr原理
shared_ptr实际上是对裸指针进行了一层封装,成员变量除了裸指针之外,还有一个引用计数,它记录裸指针被引用的次数(有多少个shared_ptr指向这同一个裸指针),当引用计数为0时,自动释放裸指针指向的资源。影响引用次数的场景包括:构造、赋值、析构。基于三个最简单的场景,实现一个demo版shared_ptr如下(实现既不严谨也不安全,仅用于阐述原理):
//智能指针的实现
#include<iostream>
using namespace std;
#include<memory>
template<class T>
class MyShared_ptr
{
public:
//构造函数
explicit MyShared_ptr(T *p = NULL)
{
this->m_ptr = p;
this->m_count = new size_t;
if (p == NULL)
{
*this->m_count = 0;
}
else
{
*this->m_count = 1;
}
}
//析构函数
~MyShared_ptr()
{
if (this->m_ptr)
{
if (*(--this->m_count) == 0)
{
delete this->m_ptr;
delete this->m_count;
this->m_ptr = NULL;
this->m_count = NULL;
}
}
}
//拷贝构造函数
MyShared_ptr(const MyShared_ptr& shared)
{
if (this != &shared)
{
this->m_ptr = shared.m_ptr;
this->m_count = shared.m_count;
(*this->m_count)++;
}
}
//重载赋值操作符
MyShared_ptr& operator=(const MyShared_ptr& shared)
{
if (this->m_ptr == shared.m_ptr)
{
return *this;
}
if (this->m_ptr)
{
if (*(--this->m_count) == 0)
{
delete this->m_ptr;
delete this->m_count;
this->m_ptr = NULL;
this->m_count = NULL;
}
}
this->m_ptr = shared.m_ptr;
this->m_count = shared.m_count;
(*this->m_count)++;
return *this;
}
//重载->操作符
T& operator->()
{
if (this->m_ptr)
{
return this->m_ptr;
}
}
//重载 *
T& operator*()
{
if (this->m_ptr)
{
return *(this->m_ptr);
}
}
//实现 use_count函数
size_t use_count()
{
return *this->m_count;
}
private:
T *m_ptr; //内部指针,保证拷贝指向同一内存
size_t *m_count; //为了保证指针的引用计数,这里我是用了指针来做
};
weak_ptr的原理。
weak_ptr又叫做弱指针,它是用来解决shared_ptr循环引用的问题。为啥叫弱呢?shared_ptr A被赋值给shared_ptr B时,A的引用计数加1,;shared_ptr A被赋值给weak_ptr C时,A的引用计数不变。
weak_ptr在使用时,是与shared_ptr绑定的。基于SharedPtr实现来实现demo版的WeakPtr,并解决循环引用的问题,全部代码如下:
template<typename T>
class SharedPtr {
public:
int* counter;
int* weakref;
T* resource;
SharedPtr(T* resc = nullptr) {
cout << __PRETTY_FUNCTION__ << endl;
counter = new int(1);
weakref = new int(0);
resource = resc;
}
SharedPtr(const SharedPtr& rhs) {
cout << __PRETTY_FUNCTION__ << endl;
resource = rhs.resource;
counter = rhs.counter;
++*counter;
}
SharedPtr& operator=(const SharedPtr& rhs) {
cout << __PRETTY_FUNCTION__ << endl;
--*counter;
if (*counter == 0) {
delete resource;
}
resource = rhs.resource;
counter = rhs.counter;
++*counter;
}
~SharedPtr() {
cout << __PRETTY_FUNCTION__ << endl;
--*counter;
if (*counter == 0) {
delete counter;
delete resource;
}
}
int use_count() {
return *counter;
}
};
template<typename T>
class WeakPtr {
public:
T* resource;
WeakPtr(T* resc = nullptr) {
cout << __PRETTY_FUNCTION__ << endl;
resource = resc;
}
WeakPtr& operator=(SharedPtr<T>& ptr) {
cout << __PRETTY_FUNCTION__ << endl;
resource = ptr.resource;
++*ptr.weakref; // 赋值时引用计数counter不变,改变弱引用计数weakref
}
~WeakPtr() {
cout << __PRETTY_FUNCTION__ << endl;
}
};
unique_ptr
template<typename T>
class PointerDeleter{
public:
void operator() (const T *_ptr){
if(_ptr){
delete _ptr;
_ptr = nullptr;
}
}
};
template<typename T, typename Delete = PointerDeleter<T>>
class UniquePtr{
private:
T *_ptr;
public:
// -----------------------------
explicit UniquePtr(T *ptr = nullptr) : _ptr(ptr){}
~UniquePtr(){
if(_ptr){
delete _ptr;
_ptr = nullptr;
}
}
//---------------------------------------------
// non-copyable
UniquePtr(const UniquePtr & p) = delete ;
UniquePtr & operator = (const UniquePtr & p) = delete ;
// move constructor
UniquePtr(UniquePtr && p) : _ptr(p._ptr){
p._ptr = nullptr;
}
// move assignment
UniquePtr& operator=(UniquePtr && p) noexcept {
std::swap(this->_ptr, p._ptr);
return *this;
}
//---------------------------------------
T & operator*(){
return *(this->_ptr);
}
T *operator->(){
return this->_ptr;
}
operator bool (){
return this->_ptr;
}
T *get() const {
return this->_ptr;
}
T *release(){
T *pointer = this->_ptr;
this->_ptr = nullptr;
return pointer;
}
void reset (T *ptr) {
UniquePtr<T, Delete>().swap(*this);
this->_ptr = ptr;
}
void swap(UniquePtr &p) {
std::swap(this->_ptr, p._ptr);
}
};