基础三大组件
1. 自定义删除器 + 数组特化
- 普通删除器:
operator()里delete ptr - 数组特化版本:
operator()里delete[] ptr - 作用:统一普通对象 / 数组的释放方式,解耦销毁逻辑
2. 引用计数块(计数器类 my_rescount)
成员:
- 资源指针:
_Ty* _mptr保存托管对象地址 - 强引用:
atomic<int> uses记录 shared_ptr 个数 - 弱引用:
atomic<int> weaks记录 weak_ptr 关联数
必须实现的接口:
- 构造函数:初始化资源指针、
uses=1、weaks=1 - 强引用自增:
increase_s()拷贝 shared_ptr 调用 - 弱引用自增:
increase_w()拷贝 weak_ptr 调用 - 获取强计数:
uses_count()返回 uses.load () - 获取弱计数:
weak_count()返回 weaks.load () - 强引用自减:
reduce_s()``--uses到 0 → 销毁托管资源 + 调用弱引用减 1 - 弱引用自减:
reduce_w()``--weaks到 0 → 销毁计数块自身
3. 核心智能指针类 my_shared_ptr
内部三个成员:
_Ty* _mptr:指向托管的真实资源my_rescount<_Ty>* _count:指向堆上唯一的计数块_Dx _deleter:删除器对象
必须实现的成员函数:
-
构造相关
-
普通构造:
my_shared_ptr(_Ty* p)有资源就new 一个计数块让_count指向 -
析构函数:调用
reset()自动计数减一、释放资源 -
拷贝 / 移动语义
-
拷贝构造 :共享资源和计数块 →
uses++ -
拷贝赋值:先释放旧资源,再共享新资源、计数 ++
-
移动构造:抢夺对方资源和计数,对方置空
-
移动赋值:清空自身、抢夺对方资源,对方置空
-
核心功能接口
-
reset():放弃当前资源,计数减一,为 0 则释放资源 -
reset(指针):放弃旧资源,接管新资源、新建计数块 -
get():返回原生裸指针 -
swap():交换两个 shared_ptr 的资源和计数块 -
运算符重载
-
operator*:解引用 -
operator->:成员访问 -
operator bool:判空(是否托管有效资源)
cpp
//测试类
class Int
{
private:
int value;
public:
Int() :value(0) { cout << "Int()\n" << value << endl; }
Int(int x) :value(x) { cout << "Int(int x)\n" << value << endl; }
~Int() { cout << "~Int()" << endl; }
Int(const Int &other) :value(other.value) { cout << "copy Int(Int other)\n" << value << endl; }
Int& operator=(const Int& other)
{
if (this != &other)
{
value = 0;
value = other.value;
}
cout << "move" << endl;
return *this;
}
};
//删除器
template<class _Ty>
struct my_delete
{
void operator()(_Ty* p)const
{
delete p;
}
};
//特化删除器
template<class _Ty>
struct my_delete<_Ty[]>
{
void operator()(_Ty* p)const
{
delete[]p;
}
};
//计数器
template<class _Ty>
class my_rescount
{
//公共接口
public:
using element_type = _Ty;
using pointer = _Ty*;
//类成员
private:
//指针
pointer _mptr;
//uses计数器,原子类型
std::atomic<int>uses;
//weaks计数器
std::atomic<int>weaks;
//普通接口函数
public:
//构造函数
my_rescount(pointer o_mptr) :
_mptr(o_mptr), uses(0), weaks(0)
{
if (_mptr != nullptr)
{
uses = 1;
weaks = 1;
}
}
//析构函数
~my_rescount()= default;
//拷贝一次shared_ptr计数加1
void increase_s()
{
++uses;
}
//拷贝一次weak_ptr计数加1
void increase_w()
{
++weaks;
}
//返回值
int uses_count()const
{
return uses.load();
}
int weak_count()const
{
return weaks.load();
}
//删一次shared_ptr减减,减为零时调用reduce_w,返回
int reduce_s()
{
if (--uses==0)
{
reduce_w();
}
return uses.load();
}
//删一次Weak_ptr减减,减为零时返回
int reduce_w()
{
if (--weaks != 0) {
}
return weaks.load();
}
};
//普通模版
template<class _Ty,class _Dx=my_delete<_Ty>>
class my_shared_ptr
{
//公共接口
public:
using pointer = _Ty*;
using element_type = _Ty;
using my_deleter = _Dx;
using my_count = my_rescount<_Ty>*;
//成员
private:
pointer _mptr;
my_count _count;
my_deleter _deleter;
//公共接口函数
public:
//删除当前智能指针,首先指向计数器的指针不为空,其次uses数量为0,也要判断weak的数量,数量为0,一起删
void reset()
{
if (_count != nullptr && _count->reduce_s() == 0)
{
_deleter(_mptr);
if (_count->reduce_w() == 0)
{
delete _count;
}
_mptr = nullptr;
_count = nullptr;
}
}
//删除当前指针,并且赋予新的指针,新的指针要有新的计数器,要重新申请
void reset(pointer p)
{
reset();
_mptr = p;
//有了新指针,就会有新的计数器继续计数
if (_mptr != nullptr)
{
_count = new my_rescount<_Ty>(_mptr);
}
}
//看一眼智能指针
pointer get()const
{
return get();
}
//获取删除器
my_deleter get_delete()const
{
return _deleter;
}
//交换函数
void swap(my_shared_ptr& other)
{
std::swap(other._mptr, this->_mptr);
std::swap(other._count, this->_count);
}
//运算符重载
_Ty& operator*()
{
return *get();
}
pointer operator->()
{
return get();
}
operator bool()
{
return get() != nullptr;
}
public:
//构造函数
my_shared_ptr(pointer p=nullptr) :_mptr(p), _count(nullptr)
{
if (_mptr != nullptr)
{
//在堆上创建了一个计数器并且让_count指向计数器,new表达式返回的就是新对象的地址
_count = new my_rescount<_Ty>(_mptr);
}
}
//析构函数
~my_shared_ptr()
{
reset();
}
//拷贝构造
my_shared_ptr(const my_shared_ptr& other) :_mptr(other._mptr), _count(other._count)
{
if (_mptr != nullptr)
{
_count->increase_s();
}
}
//移动构造
my_shared_ptr(my_shared_ptr&& other) :_mptr(other._mptr), _count(other._count)
{
other._mptr = nullptr;
other._count = nullptr;
}
//赋值
my_shared_ptr& operator=(const my_shared_ptr& other)
{
my_shared_ptr(other).swap(*this);
return *this;
}
//移动赋值
my_shared_ptr& operator=(my_shared_ptr&& other)
{
my_shared_ptr(std::move(other)).swap(*this);
cout << "std::move" << endl;
return *this;
}
};
//普通模版
template<class _Ty, class _Dx>
class my_shared_ptr<_Ty[],_Dx>
{
//公共接口
public:
using pointer = _Ty*;
using element_type = _Ty;
using my_deleter = _Dx;
using my_count = my_rescount<_Ty>*;
//成员
private:
pointer _mptr;
my_count _count;
my_deleter _deleter;
//公共接口函数
public:
//删除当前智能指针,首先指向计数器的指针不为空,其次uses数量为0,也要判断weak的数量,数量为0,一起删
void reset()
{
if (_count != nullptr && _count->reduce_s() == 0)
{
_deleter(_mptr);
if (_count->reduce_w() == 0)
{
delete _count;
}
_mptr = nullptr;
_count = nullptr;
}
}
//删除当前指针,并且赋予新的指针,新的指针要有新的计数器,要重新申请
void reset(pointer p)
{
reset();
_mptr = p;
//有了新指针,就会有新的计数器继续计数
if (_mptr != nullptr)
{
_count = new my_rescount<_Ty>(_mptr);
}
}
//看一眼智能指针
pointer get()const
{
return get();
}
//获取删除器
my_deleter get_delete()const
{
return _deleter;
}
//交换函数
void swap(my_shared_ptr& other)
{
std::swap(other._mptr, this->_mptr);
std::swap(other._count, this->_count);
}
//运算符重载
_Ty& operator[](int index)
{
return get()[index];
}
operator bool()
{
return get() != nullptr;
}
public:
//构造函数
my_shared_ptr(pointer p = nullptr) :_mptr(p), _count(nullptr)
{
if (_mptr != nullptr)
{
//在堆上创建了一个计数器并且让_count指向计数器,new表达式返回的就是新对象的地址
_count = new my_rescount<_Ty>(_mptr);
}
}
//析构函数
~my_shared_ptr()
{
reset();
}
//拷贝构造
my_shared_ptr(const my_shared_ptr& other) :_mptr(other._mptr), _count(other._count)
{
if (_mptr != nullptr)
{
_count->increase_s();
}
}
//移动构造
my_shared_ptr(my_shared_ptr&& other) :_mptr(other._mptr), _count(other._count)
{
other._mptr = nullptr;
other._count = nullptr;
}
//赋值
my_shared_ptr& operator=(const my_shared_ptr& other)
{
my_shared_ptr(other).swap(*this);
return *this;
}
//移动赋值
my_shared_ptr& operator=(my_shared_ptr&& other)
{
my_shared_ptr(std::move(other)).swap(*this);
cout << "std::move" << endl;
return *this;
}
};
void funa()
{
my_shared_ptr<Int>pa(new Int(10));
my_shared_ptr<Int>pb;
pb = std::move(new Int(12));
my_shared_ptr<Int>pc;
pc = pb;
}
void funb()
{
my_shared_ptr<Int[]>pa(new Int[10]);
printf("\n");
my_shared_ptr<Int[]>pb;
pb = std::move(new Int[12]);
my_shared_ptr<Int[]>pc;
pc = pb;
}
int main()
{
funa();
funb();
}