一、shared_ptr的内存结构

在这里插入图片描述

结构解释:

  • _Ptr和_Ref分别保存存放在堆区空间的被管理对象和引用计数结构
  • 引用计数结构中的_rptr也保存被管理对象的地址。
  • _Users记录shared_ptr指针管理对象的个数
  • _Weaks记录weak_ptr管理对象的个数

二、删除器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//单个对象删除器
template<class _Ty>
class Deleter
{
Deleter() = default;
public:
void operator()(_Ty* p = NULL)const
{
if (p != NULL)
{
delete p;
}
}
};

//一组对象删除器
template<class _Ty>
class Deleter<_Ty[]>
{
Deleter() = default;
public:
void operator()(_Ty* p = NULL)const
{
if (p != NULL)
{
delete[] p;
}
}
};

三、引用计数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//引用计数结构
template<class _Ty>
class Rfc
{
private:
_Ty* _rPtr; //指向被管理对象
atomic_int _Users; //shared_ptr引用个数
atomic_int _Weaks; //weak_ptr引用个数
public:
Rfc(_Ty* p = NULL) :_rPtr(p), _Users(1), _Weaks(1)
{}
~Rfc() {}
//增加_Users
void IncRef_Users()
{
++_Users;
}
//增加_Weaks
void IncRef_Weaks()
{
++_Weaks;
}
};

四、shared_ptr仿写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//单个对象shared_ptr结构
template<class _Ty, class Deleter_T = Deleter<_Ty>>
class shared_ptr
{
private:
_Ty* _Ptr; //保存被管理对象的地址
Rfc<_Ty>* _Ref; //保存引用计数结构的地址
Deleter_T _deleter; //删除器

public:
shared_ptr(_Ty* p = NULL) : _Ptr(p), _Ref(NULL)
{
if (_Ptr != NULL)
{
__Ref = new Rfc<_Ty>(p);
}
}
shared_ptr(const shared_ptr& src): _Ptr(src._Ptr), _Ref(src._Ref)
{
if (_Ref != NULL)
{
_Ref->Incref_Users();
}
}
shared_ptr(shared_ptr&& rval): _Ptr(rval._Ptr), _Ref(rval._Ref)
{
rval._Ptr = NULL;
rval._Ref = NULL;
}
shared_ptr& operator=(const shared_ptr& src)
{
if (this == &src || _Ptr == src._Ptr)
return *this;
if (_Ptr != NULL && --_Ref->_Users == 0)
{
_deleter(_Ptr);
if (--_Ref->_Weaks == 0)
{
delete _Ref;
}
}
_Ptr = src._Ptr;
_Ref = src._Ref;
if (_Ptr != NULL)
{
_Ref->IncRef_Users();
}
return *this;
}
shared_ptr& operator=(shared_ptr&& rval)
{
//p = std::move(p)
if (this == &rval)
return *this;
//p = fun() return share_ptr
if (_Ptr != NULL && rval._Ptr != NULL && _Ptr == rval._Ptr)
{
--_Ref->_Users;
rval._Ptr = NULL;
rval._Ref = NULL;
return *this;
}
if (_Ptr != NULL && --_Ref->_Users == 0)
{
_deleter(_Ptr);
if (--_Ref->_Weaks == 0)
{
delete _Ref;
}
}
_Ptr = rval._Ptr;
_Ref = rval._Ref;
rval._Ptr = NULL;
rval._Ref = NULL;
return *this;
}

~shared_ptr()
{
if (_Ref != NULL && --_Ref->_Users == 0)
{
_deleter(_Ptr);
if (--_Ref->_Weaks == 0)
{
delete _Ref;
}
}
}

_Ty* get()const
{
return _Ptr;
}
_Ty* operator->()
{
return get();
}
_Ty& operator*()
{
return *get();
}
size_t use_count()const
{
return _Ref->_Users;
}
void swap(shared_ptr& src)
{
std::swap(_Ptr, src._Ptr);
std::swap(_Ref, src._Ref);
}
operator bool()const
{
return _Ptr != NULL;
}
private:
friend class weak_ptr<_Ty>;
};

五、关于weak_ptr

定义于头文件

1
2
3
template< class T > class weak_ptr;
// (C++11 起)

std::weak_ptr 是一种智能指针,它对被 std::shared_ptr 管理的对象存在非拥有性(「弱」)引用。在访问所引用的对象前必须先转换为 std::shared_ptr。

std::weak_ptr 用来表达临时所有权的概念:当某个对象只有存在时才需要被访问,而且随时可能被他人删除时,可以使用 std::weak_ptr 来跟踪该对象。需要获得临时所有权时,则将其转换为 std::shared_ptr,此时如果原来的 std::shared_ptr 被销毁,则该对象的生命期将被延长至这个临时的 std::shared_ptr 同样被销毁为止。

std::weak_ptr 的另一用法是打断 std::shared_ptr 所管理的对象组成的环状引用。若这种环被孤立(例如无指向环中的外部共享指针),则 shared_ptr 引用计数无法抵达零,而内存被泄露。能令环中的指针之一为弱指针以避免此情况。

六、weak_ptr与shared_ptr关联内存结构

在这里插入图片描述


七、weak_ptr仿写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//weak_ptr
template<class _Ty>
class weak_ptr
{
private:
Rfc<_Ty>* _Rp;
public:
weak_ptr(Rfc<_Ty>* p = NULL) : _Rp(p)
{}
weak_ptr(const shared_ptr<_Ty>& src) : _Rp(src._Ref)
{
if (_Rp != NULL)
{
_Rp->IncRef_Weaks();
}
}
weak_ptr(const weak_ptr& src) : _Rp(src._Ref)
{
if (_Rp != NULL)
{
_Rp->IncRef_Weaks();
}
}
~weak_ptr()
{
if (_Rp != NULL && --_Rp->_Weaks == 0)
{
delete _Rp;
}
}
weak_ptr& operator=(const weak_ptr& src)
{
if (this == &src || _Rp == src._Rp)
return *this;
if (_Rp != NULL && --_Rp->_Weaks == 0)
{
delete _Rp;
}
_Rp = src._Rp;
if (_Rp != NULL)
{
_Rp->IncRef_Weaks();
}
return *this;
}
weak_ptr& operator=(weak_ptr&& rval)
{
if (this == &rval || _Rp == rval._Rp) return *this;
if (_Rp != NULL && rval._Rp != NULL && _Rp == rval._Rp)
{
--_Rp->_Weaks;
rval._Rp = NULL;
return *this;
}
if (_Rp != NULL && --_Rp->_Weaks == 0)
{
delete _Rp;
}
_Rp = rval._Rp;
rval._Rp = NULL;
return *this;
}

weak_ptr& operator=(const shared_ptr<_Ty>& src)
{
if (_Rp != NULL && --_Rp->_Weaks == 0)
{
delete _Rp;
}
_Rp = src._Ref;
if (_Rp != NULL)
{
_Rp->IncRef_Weaks();
}
return *this;
}
weak_ptr& operator=(shared_ptr<_Ty>&& rval) = delete;

//检查关联对象是否被删除
bool expired()const
{
return _Rp->_Users == 0;
}
void swap(weak_ptr& src)
{
std::swap(_Rp, src._Rp);
}
//创建管理被引用的对象的shared_ptr
shared_ptr<_Ty> lock()
{
shared_ptr<_Ty> tmp;
tmp._Ptr = _Rp->_rPtr;
tmp._Ref = _Rp;
tmp._Ref->IncRef_Users();
return tmp;
}
};