目录
1.weak_ptr
weak_ptr是为了配合shared_ptr而引入的智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期;不论是否有weak_ptr的指向,一个指向对象的shared_ptr被销毁,对象就会释放。更像是shared_ptr的助手,但weak_ptr拥有一套不纳入计数器的指针系统
2.源码
//weak_ptr
//弱引用--父子关系的问题
//--弱引用克服循环引用,
template<class _Ty>
class MyDeletor
{
public:
MyDeletor() {}
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
delete ptr;
}
};
template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
MyDeletor() = default;//明确的告知有构造函数
void operator()(_Ty* ptr) const
{
if (ptr != nullptr)
delete[] ptr;
}
};
template<class _Ty>
class RefCnt
{
public:
_Ty* _Ptr;
std::atomic_int _Uses;
std::atomic_int _Weaks;
public:
RefCnt(_Ty* p):_Ptr(p),_Uses(1),_Weaks(1){}
~RefCnt(){}
void _Incref() { _Uses += 1; }//shared_ptr引用计数
void _Incwref() { _Weaks += 1; }//weak_ptr引用计数
};
template<class _Ty>
class my_weak_ptr;
template <class _Ty,class _Dx=MyDeletor<_Ty>>
class my_shared_ptr
{
private:
_Ty* _Ptr;
RefCnt<_Ty>* _Rep;
_Dx _mDeletor;
public:
my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
{
if (p != NULL)
{
_Ptr = p;
_Rep = new RefCnt<_Ty>(p);
}
}
//拷贝构造--构造一个对象
my_shared_ptr(const my_shared_ptr& _Y):_Ptr(_Y._Ptr),_Rep(_Y._Ptr)
{
if (_Rep != nullptr)
{
_Rep->_Incref();
}
}
//移动构造
//my_shared_ptr(my_shared_ptr&& other):_Ptr(nullptr),_Rep(nullptr)
//{swap(*this,other._Ptr);}
my_shared_ptr(my_shared_ptr&& other) :_Ptr(other._Ptr), _Rep(other._Rep)
{
other._Ptr = nullptr;
other._Rep = nullptr;
}
~my_shared_ptr()
{
if (_Rep != nullptr && --_Rep->_Uses == 0)
{
_mDeletor(_Ptr);
if (_Rep->_Weaks == 0)
{
delete _Rep;
}
}
_Ptr = nullptr;
_Rep = nullptr;
}
my_shared_ptr& operator=(const my_shared_ptr& r)
{
if (this == r || this->_Ptr == r._Ptr) return *this;
if (_Ptr != nullptr && --_Rep->_Uses == 0)
{
_mDeletor(_Ptr);
if (--_Rep->_Weaks == 0)
{
delete _Rep;
}
}
_Ptr = r._Ptr;
_Rep = r._Rep;
if (_Ptr != nullptr)
{
_Rep->_Incref();
}
return *this;
}
my_shared_ptr& operator=(const my_shared_ptr&& other)
{
if (this == &other)return*this;
if (_Ptr != nullptr && other._Ptr != nullptr && _Ptr == other->_Ptr)
{
this->_Rep->_Uses -= 1;
other._Ptr = nullptr;
other._Rep = nullptr;
return*this;
}
if (_Ptr != nullptr && --_Rep->_Uses == 0)
{
_mDeletor(_Ptr);
if (--_Rep->_Weaks == 0) {
delete _Rep;
}
}
_Ptr = other._Ptr;
_Rep = other._Rep;
_Ptr = nullptr;
_Rep = nullptr;
return *this;
}
//获取对象的指针
//*
_Ty* get()const { return _Ptr; }
//返回对象自身
_Ty& operator*()const { return *get(); }
_Ty* operator->()const { return get(); }
size_t use_count()const
{
if (_Rep == nullptr) return 0;
return _Rep->_Uses;
}
void swap(my_shared_ptr&& r)
{
std::swap(_Ptr, r._Ptr);
std::swap(_Ptr, r.Ptr);
}
//是否持有对象
operator bool()const { return _Ptr != nullptr; }
template<class _Ty>
friend class my_weak_ptr;
};
template<class _Ty>
class my_weak_ptr
{
private:
RefCnt<_Ty>* _Rep;
public:
my_weak_ptr() :_Rep(nullptr) {}
my_weak_ptr(const my_shared_ptr<_Ty>& other) :_Rep(other._Rep)
{
if (_Rep != nullptr)
{
_Rep->_Incwref();
}
}
//弱引用计数只加弱引用计数的个数,强引用也一样
//析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
//弱引用计数只能析构计数结构,不能析构对象
my_weak_ptr(const my_weak_ptr& other) :_Rep(other._Rep)
{
if (_Rep != nullptr)
{
_Rep->_Incwref();
}
}
my_weak_ptr(my_weak_ptr&& other) :_Rep(other._Rep)
{
other._Rep = nullptr;
}
my_weak_ptr& operator=(const my_weak_ptr& other)
{
if (this == &other || this->_Rep == other) return *this;
if (_Rep != nullptr && --_Rep->_Weaks == 0)
{
delete _Rep;
}
_Rep = other->_Rep;
if (_Rep != nullptr)
{
_Rep->_Incwref();
}
return *this;
}
my_weak_ptr& operator=(my_weak_ptr&& other)
{
if (this == &other) return *this;
if (this->_Rep != nullptr && other._Rep != nullptr && _Rep == other._Rep)
{
this->_Rep ->_Weaks -= 1;
other._Rep = nullptr;
return *this;
}
if (_Rep != nullptr && --_Rep->_Weaks == 0)
{
delete _Rep;
}
_Rep = other._Rep;
other._Rep = nullptr;
return *this;
}
my_weak_ptr& operator=(const my_shared_ptr<_Ty>& other)
{
if (_Rep != nullptr && --_Rep->_Weaks == 0)
{
delete _Rep;
}
_Rep = other._Rep;
if (_Rep != nullptr)
{
_Rep->_Incwref();
}
return *this;
}
//不能进行移动赋值
// 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
// 弱引用检测RefCnt结构是否存在,解决环形引用
my_weak_ptr& operator=(my_shared_ptr<_Ty>&& other) = delete;
~my_weak_ptr()
{
if (_Rep != nullptr && --_Rep->_Weaks == 0)
{
delete _Rep;
}
_Rep = nullptr;
}
//检测被引用的对象是否被删除//true删除
bool expired()const
{
return this->_Rep->_Uses==0;
}
//弱引用没有重载指向符
//锁住弱引用锁住的对象
//构建临时对象,指针全都给该对象
my_shared_ptr<_Ty> lock()const
{
my_shared_ptr<_Ty> _Ret;
_Ret._Ptr = _Rep->_Ptr;
_Ret._Rep = _Rep;
_Ret._Rep->_Incref();
return _Ret;
}
};
3.注意:
//弱引用计数只加弱引用计数的个数,强引用也一样
//析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
//弱引用计数只能析构计数结构,不能析构对象
//不能进行移动赋值
// 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
// 弱引用检测RefCnt结构是否存在,解决环形引用
如何判断weak_ptr指向的对象是否还存在---lock()函数实现
//弱引用计数只加弱引用计数的个数,强引用也一样
//析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
//弱引用计数只能析构计数结构,不能析构对象
//不能进行移动赋值
// 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
// 弱引用检测RefCnt结构是否存在,解决环形引用
如何判断weak_ptr指向的对象是否还存在---lock()函数实现
4.用weak_ptr克服循环引用
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x) { cout << "Object" << endl; }
~Object() { cout << "~Object" << endl; }
};
//--弱引用克服循环引用,对象销毁的顺序?
class Child;
class Parent
{
public:
my_weak_ptr<Child> c;
public:
Parent() { cout << "Parent" << endl; }
~Parent() { cout << "~Parent" << endl; }
void hi()const { cout << "hello parent" << endl; }
};
class Child
{
public:
my_weak_ptr<Parent> p;
Child() { cout << "Child" << endl; }
~Child() { cout << "Child" << endl; }
};
void fun()
{
my_shared_ptr<Parent> parent(new Parent());
my_shared_ptr<Child> child(new Child());
parent->c = child;
child->p = parent;
child->p.lock()->hi();
}
对象销毁顺序
//基础的构建weak_ptr在内存中的
void fun()
{
my_shared_ptr<Object> op1(new Object(10));
my_weak_ptr<Object> wp1(op1);
my_weak_ptr<Object> wp2(op1);
}