文章目录
前言
简单介绍shared_ptr与weak_ptr,仿写系统的shared_ptr与weak_ptr,并解决循环引用的问题.
提示:以下是本篇文章正文内容,下面案例可供参考
一、shared_ptr与weak_ptr是什么?
shared_ptr是一种智能指针(smart pointer),作用有如同指针,但会记录有多少个shared_ptrs共同指向一个对象。这便是所谓的引用计数(reference counting)。一旦最后一个这样的指针被销毁,也就是一旦某个对象的引用计数变为0,这个对象会被自动删除。
weak_ptr是为配合shared_ptr而引入的一种智能指针。
1.shared_ptr的内存模型
2.weak_ptr的内存模型
二、仿写系统的shared_ptr与weak_ptr
1.mdeletor
```cpp
class Mdeletor
{
public:
Mdeletor() = default;
void operator()(_Ty* p)const
{
if (p != NULL)
{
delete p;
}
p = NULL;
}
};
template<typename _Ty>
class Mdeletor<_Ty[]>
{
public:
Mdeletor() = default;
void operator()(_Ty* p)const
{
if (p != NULL)
{
delete[]p;
}
p = NULL;
}
};
2.Ref_con
template<typename _Ty>
class RefCnt
{
protected:
_Ty* ptr;
std::atomic_int Uses;
std::atomic_int Weaks;
public:
RefCnt(_Ty* p) :ptr(p), Uses(1), Weaks(1) {}
~RefCnt() {}
void IncUses()
{
Uses += 1;
}
void IncWeaks()
{
Weaks += 1;
}
template<typename _Ty, typename _Dx>
friend class my_shared_ptr;
template<typename _Ty>
friend class my_weak_ptr;
};
3.shared_ptr
代码如下(示例):
template<typename _Ty,typename _Dx= Mdeletor<_Ty>>
class my_shared_ptr
{
private:
_Ty* Ptr;
RefCnt<_Ty>* Ref;
_Dx mdeletor;
public:
my_shared_ptr(_Ty* p = nullptr) :Ptr(nullptr),Ref(nullptr)
{
if (p != nullptr)
{
Ptr = p;
Ref = new RefCnt<_Ty>(p);
}
}
my_shared_ptr(const my_shared_ptr& other):Ptr(other.Ptr),Ref(other.Ref)//拷贝构造
{
if (Ptr != NULL)
{
Ref->IncUses();
}
}
my_shared_ptr(my_shared_ptr&& other) :Ptr(other.Ptr), Ref(other.Ref)//移动构造
{
other.Ptr = NULL;
other.Ref = NULL;
}
my_shared_ptr& operator=(const my_shared_ptr& other)//赋值
{
if (this == &other || Ptr == other.Ptr) return *this;//自赋值,直接返回本身
if (Ptr != NULL && --Ref->Uses == 0)//被赋值的智能指针对象拥有资源,
{ //且该对象仅被该智能指针拥有
mdeletor(Ptr);//释放该对象
if (--Ref->Weaks == 0)//当弱引用计数为零时
{
delete Ref;//析构引用计数对象
Ref = NULL;
}
}
Ptr = other.Ptr;
Ref = other.Ref;
if (Ptr != NULL)
{
Ref->IncUses();
}
return *this;
}
my_shared_ptr& operator=(my_shared_ptr&& other)//移动赋值
{
if (this == &other) return *this;
if (Ptr == other.Ptr && Ptr != NULL)//当两个智能指针使用同一个对象时,且该对象不为空
{
other.Ptr = NULL;//去掉other的使用权
other.Ref = NULL;
Ref->Uses -= 1;//强引用计数-1
return *this;
}
if (Ptr != NULL && --Ref->Uses == 0)
{
mdeletor(Ptr);
if (--Ref->Weaks == 0)
{
delete Ref;
Ref = NULL;
}
}
Ptr = other.Ptr;
Ref = other.Ref;
other.Ptr = NULL;
other.Ref = NULL;
return *this;
}
~my_shared_ptr()
{
if (Ptr != NULL && --Ref->Uses == 0)
{
mdeletor(Ptr);
if (--Ref->Weaks == 0)
{
delete Ref;
}
}
Ref = NULL;
}
_Ty* get()const
{
return Ptr;
}
_Ty& operator*()
{
return *get();
}
_Ty* operator->()
{
return get();
}
size_t use_count()const
{
if (Ref == NULL) return 0;
return Ref->Uses;
}
void swap(my_shared_ptr& other)
{
std::swap(Ptr, other.Ptr);
std::swap(Ref, other.Ref);
}
operator bool()const
{
return Ptr != NULL;
}
template<typename _Ty>
friend class my_weak_ptr;
};
4.weak_ptr
代码如下(示例):
template<typename _Ty>
class my_weak_ptr
{
private:
RefCnt<_Ty>* wRef;
public:
my_weak_ptr() :wRef(NULL) {}
my_weak_ptr(const my_shared_ptr<_Ty>& other) :wRef(other.Ref)//共享指针构造
{
if (wRef!=NULL)
{
wRef->IncWeaks();
}
}
my_weak_ptr(const my_weak_ptr& other) :wRef(other.wRef)//拷贝构造
{
if (wRef != NULL)
{
wRef->IncWeaks();
}
}
my_weak_ptr(my_weak_ptr&& other) :wRef(other.wRef)//移动构造
{
other.wRef = NULL;
}
my_weak_ptr& operator=(const my_weak_ptr& other)
{
if (this == &other||wRef=other.wRef) return *this;//自赋值或者是两个指针指向同一个对象
if (this != NULL && --wRef->Weaks == 0)//是否自己独占对象
{
delete wRef;
}
wRef = other.wRef;
if (wRef != NULL)
{
wRef->IncUses();
}
return *this;
}
my_weak_ptr& operator=(my_weak_ptr&& other)
{
//1 判断是否自赋值
if (this == &other) return *this;
//2 判断是否是指向同一个对象的两个指针相互赋值
if (wRef == other.wRef && wRef != NULL)//如果是
{
other.wRef = NULL;
wRef->Weaks -= 1;
return *this;
}
//3 两个指向不同对象的指针赋值
if (this != NULL && --wRef->Weaks == 0)//是否自己独占对象
{
delete wRef;//如果独有
}
wRef = other.wRef;
other.wRef = NULL;
return *this;
}
my_weak_ptr& operator=(const my_shared_ptr<_Ty>& other)//共享智能指针给弱指针赋值
{
if (wRef == other.Ref) return *this;
if (wRef != NULL && --wRef->Uses == 0)
{
delete wRef;
}
wRef = other.Ref;
if (wRef != NULL)
{
wRef->IncWeaks();
}
return *this;
}
my_weak_ptr& operator=( my_shared_ptr<_Ty>&& other) = delete;
~my_weak_ptr()
{
if (wRef != NULL && --wRef->Weaks == 0)
{
delete wRef;
}
wRef = NULL;
}
bool expired()const//判断被引用的对象是否删除,若删除则返回真
{
return wRef->Uses == 0;
}
my_shared_ptr<_Ty> lock()const
{
my_shared_ptr<_Ty>tmp;
tmp.Ptr = wRef->ptr;
tmp.Ref = wRef;
tmp.Ref->IncUses();
return tmp;
}
};
该处使用的url网络请求的数据。
三、解决循环引用问题
四、总结
weak_ptr一般需要与shared_ptr联合使用,且若要使用weak_ptr时需要用lock()函数返回一个shared_ptr的对象再进行使用。