目录
- class Child;
- class Parent {
- public:
- shared_ptr
_child; - ~Parent() {
- cout << " Destroy Parent" << endl;
- }
- void hi()const {
- cout << "hello" << endl;
- }
- };
- class Child {
- public:
- shared_ptr
parent; - ~Child() {
- cout << " Bey child" << endl;
- }
- };
- int main() {
- shared_ptr
par = make_shared(); - shared_ptr
pch = make_shared(); - par->_child = pch;
- pch->parent = par;
- pch->parent->hi();
- return 0;
- }


到最后还是没有完成析构。
上面代码的运行结果,只打印出”Hello",而并没有打印出"Bye Parent"或"Bye Child",说明Parent和Child的析构函数并没有调用到。这是因为Parent和Child对象内部,具有各自指向对方的shared _ptr,加上parent和child这两个shared_ptr, 说明每个对象的引用计数都是2。当程序退出时,即使parent和child被销毁,也仅仅是导致引用计数变为了1,因此并未销毁Parent和Child对象。

为了解决类似这样的问题,C++11 引入了weak_ptr,来打破这种循环引用。
weak ptr是为了配合shared _ptr 而引入的一种智能指针,它指向一个由shared_ptr 管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr 绑定到一个shared_ptr不会改变shared_ptr 的引用计数。不论是否有weak_ptr 指向,一旦最后一个指向对象的shared_ptr 被销毁,对象就会被释放。从这个角度看,weak_ptr 更像是shared_ptr 的一个助手而不是智能指针。weak_ptr并不拥有对动态对象的管辖权,weak_ptr 指向shared_ptr 的目标也不会增加计数器的值,相反,weak_ptr 拥有一套不纳入计数器的指针系统。
接下来,我们来看看weak_ptr的简单用法。
当我们创建一个weak_ptr 时,需要用一个shared_ptr实例来初始化weak_ptr,由于是弱共享, weak_ ptr的创建并不会影响shared_ptr 的引用计数值。
示例:
既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那就可能存在weak_ptr指向的对象被释放掉这种情况。这时,我们就不能使用weak_ptr直接的访问对象。那么如何判断weak_ptr指向的对象存在呢?
c++提供lock函数来实现该功能。
如果对象存在,lock()函数返回一个指向共享对象的shared_ptr,否则返回一个空shared_ptr。
- class Object {
- private:
- int value;
- public:
- Object(int x = 0) :value(x) { cout << "Object Create" << endl;; }
- ~Object() { cout << "Object Destroy"<
- int GetValue()const {
- return value;
- }
- };
- int main() {
- shared_ptr
- weak_ptr
- if (shared_ptr
- cout << pa->GetValue() << endl;
- }
- else {
- cout << wp.expired() << endl;//判断对象是否被销毁
- cout << "wp 引用对象为空" << endl;
- }
- return 0;
- }

3、weak_ptr的使用
weak_ptr没有重载operator->和operator *操作符号,无法访问对象,可以使用lock()访问原始对象;

- class Child;
- class Parent {
- public:
- weak_ptr
_child; - ~Parent() {
- cout << " Destroy Parent" << endl;
- }
- void hi()const {
- cout << "hello" << endl;
- }
- };
- class Child {
- public:
- weak_ptr
parent; - ~Child() {
- cout << " Bey child" << endl;
- }
- };
- int main() {
- shared_ptr
par = make_shared(); - shared_ptr
pch = make_shared(); - par->_child = pch;
- pch->parent = par;
- if (!(pch->parent.expired())) {
- pch->parent.lock()->hi();
- }
- return 0;
- }

二、仿写std::weak_ptr
1、c++参考手册

2、代码
- #ifndef MY_WEAK_PTR
- #define MY_WEAK_PTR
- #include
- 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; }
- void _Incwref() { _Weaks += 1; }
- };
- 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 != nullptr)
- {
- _Ptr = p;
- _Rep = new RefCnt<_Ty>(p);
- }
- }
- my_shared_ptr(const my_shared_ptr& _Y) :_Ptr(_Y._Ptr), _Rep(_Y._Rep)
- {
- if (_Rep != nullptr)
- {
- _Rep->_Incref();
- }
- }
- my_shared_ptr(my_shared_ptr&& other):_Ptr(other._Ptr),_Rep(other._Rep)
- {
- other._Ptr = nullptr;
- other._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 =(my_shared_ptr&& other)
- {
- if (this == &other)return *this;
- if (this->_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;
- other._Ptr = nullptr;
- other._Rep = nullptr;
- return *this;
- }
- ~my_shared_ptr()
- {
- if (_Rep != nullptr && --_Rep->_Uses == 0)
- {
- _mDeletor(_Ptr);
- if (--_Rep->_Weaks == 0)
- {
- delete _Rep;
- }
- }
- _Ptr = nullptr;
- _Rep = nullptr;
- }
- _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(_Rep, r._Rep);
- }
- operator bool()const { return _Ptr != nullptr; }
- };
- template <class _Ty>
- class my_weak_ptr
- {
- private:
- RefCnt<_Ty>* _Rep;
- public:
- my_weak_ptr() :_Rep(nullptr) {}
- my_weak_ptr(const my_weak_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._Rep)return *this;
- if (this->_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;
- }
- my_weak_ptr& operator =(my_shared_ptr<_Ty>&& other) = delete;
- ~my_weak_ptr()
- {
- if (_Rep != nullptr && --_Rep->_Weaks == 0)
- {
- delete _Rep;
- }
- _Rep = nullptr;
- }
- 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;
- }
- };
- #endif