一、概述
c++11中std::shared_ptr
_Ty *_Ptr; //被管理的动态内存指针
_Ref_count_base *_Rep; //计数器基类指针,用于指示有几个shared_ptr共享_Ptr指向的对象,
//当其字段users减1为0时寓 意对象要被销毁
二、shared_ptr 相关类的数据组织结构:
类1. // TEMPLATE CLASS _Ptr_base, shared_ptr的基类,构造函数实现字段的初始化。
template
class _Ptr_base {
public:
//[0]
constexpr _Ptr_base() _NOEXCEPT
: _Ptr(0), _Rep(0)
{
// construct
}
//重要字段
private:
_Ty *_Ptr; //被管理的动态内存指针
_Ref_count_base *_Rep; //计数器基类指针
};
类2 // TEMPLATE CLASS shared_ptr
template
class shared_ptr : public _Ptr_base<_Ty> {
public:
typedef shared_ptr<_Ty> _Myt;
template
explicit shared_ptr(_Ux *_Px) // [1]
{
// construct shared_ptr object that owns _Px
_Resetp(_Px); //[2]
}
shared_ptr(const _Myt& _Other) _NOEXCEPT // [copy construct]
{
// construct shared_ptr object that owns same resource as _Other
this->_Reset(_Other);
}
};
类3 . //引用计数器基类,包含users、weaks……字段,引用计数等逻辑
class _Ref_count_base {
private:
_Atomic_counter_t _Uses; //引用计数
_Atomic_counter_t _Weaks; //weak计数
protected:
// construct,使用原子操作将引用计数与weak计数init为1【3】
_Ref_count_base() {
_Init_atomic_counter(_Uses, 1);
_Init_atomic_counter(_Weaks, 1);
}
};
类4. template
class _Ref_count : public _Ref_count_base { // handle reference counting for object without deleter
public:
_Ref_count(_Ty *_Px) : _Ref_count_base(), _Ptr(_Px) {
// construct
}
private:
_Ty * _Ptr; // 指向动态数据的指针
};
三、构造一个shared_ptr对象的过程
构造一个shared_ptr 对象开始
|
|
\|/ |--------_Ptr(0)
首先调用基类构造函数初始化字段为空 ---|
| |--------_Rep(0)
|
\|/
在shared_ptr构造函数内调用_Resetp(_Px) //_Px为new出的数据指针
|
| 1.创建计数器对象 |------上述[3]所示
\|/ |------------------------------|
_Resetp0(_Px, new _Ref_count<_Ux>(_Px));----| |------让计数器_Ptr指向数据内存
| | 2.
| |-------------------传入数据内存指针
| <传参数>
\|/ |----1. _Ptr = _Other_ptr;(新对象的_Ptr指针init)
_Reset0(_Ty *_Other_ptr, _Ref_count_base *_Other_rep)----|
(shared_ptr 字段初始化) |
|----2. _Rep = _Other_rep;(计数器_Ref指针init)
三、拷贝构造shared_ptr
copy构造一个shared_ptr 对象开始
|
|
\|/ |--------_Ptr(0)
首先调用基类构造函数初始化字段为空[0]---|
| |--------_Rep(0)
|
\|/
this->_Reset(_Other) //_Other为【被拷贝】shared_ptr对象
|
|
| |--------【1】 递增被拷贝对象的引用计数
_Reset(_Other._Ptr, _Other._Rep)----|
| //传参数
|-----_Reset0(_Other_ptr, _Other_rep);------- //(如果_Rep不为0递减计数器)
|
| //与被拷贝对象使用同一个引用计数器
|---【1】_Rep = _Other_rep
| //拷贝对象的数据指针段指向数据内存
|---【2】_Ptr = _Other_ptr
四、拷贝构造对象与被拷贝对象的内存状态
五、总结
引用计数器是一个类类型,其中包含uses字段来记录当前引用动态对象的shared_ptr个数。一但uses-1为0动态对象
将被销毁。
实际每个shared_ptr对象共用一个“计数器”。因此在拷贝构造shared_ptr对象时,两者“都知道对方的存在”。
shared_ptr类型拷贝构造对象,原对象以及引用计数对象都指向动态数据对象。
六、结束语
现在对shared_ptr有一个较深层次的认识,以后文章将介绍原始指针与shared_ptr在使用上的一些问题。