利用模板模拟标准库智能指针代码如下:
#pragma once
#ifndef SHARED_PTR_H
#define SHARED_PTR_H
#include <iostream>
#include <functional>
///书写自己版本的Shared_ptr
template<typename _Ty>
class Shared_ptr
{
using _Del = void(*)(_Ty*); //删除器类型别名
public:
//typedef void(*)(_Ty*) _Del; //提供的删除器类型
/// Construct function
Shared_ptr() : element(nullptr), use(new int(0)) {} //默认构造
Shared_ptr(_Ty* p) :element(p), use(new int(1)) {} //传递指针构造
Shared_ptr(_Ty* p, _Del d) : element(p), use(new int(1)) { del = d; } //传递一个自定义的删除函数
Shared_ptr(const Shared_ptr& rhs) :element(rhs.element), use(rhs.use) { ++*use; } //拷贝构造,引用计数递增
Shared_ptr(Shared_ptr&& rhs) noexcept : element(rhs.element), use(rhs.use) { rhs.element = rhs.use = nullptr; } //移动构造
///重载运算符
Shared_ptr& operator=(const Shared_ptr& rhs); //拷贝赋值
Shared_ptr& operator=(Shared_ptr&& rhs) noexcept; //移动赋值
_Ty& operator*(); //解引用运算符
const _Ty& operator*() const; //解引用常量版本
_Ty* operator->() const; //重载箭头运算符
///成员函数
int use_count() const { return *use; } //返回正在使用的计数
void release(); //引用计数递减1,如果为0,则释放占用的内存
void reset(const Shared_ptr& rhs); //重新设置指针指向一个Shared_ptr对象
void reset(_Ty* p); //设置指针指向一个动态分配的指针
void reset(_Ty* p, _Del d); //设置一个指针和自定义删除类型
bool unique() const { return *use == 1; } //检查当前是否独享对象
_Ty* get() const { return element; } //返回内置指针类型
///析构函数
~Shared_ptr() { free(); } //析构函数负责调用free函数
private:
static std::function<void(_Ty*)> del; //用于保存用户提供的删除操作
_Ty* element; //绑定的元素
int *use; //使用计数。检查当前有多少个用户正在使用该指针
///工具函数 负责释放内存
void free();
};
template<typename _Ty> std::function<void(_Ty*)> Shared_ptr<_Ty>::del = nullptr; //类外定义静态成员
template<typename _Ty>
Shared_ptr<_Ty>& Shared_ptr<_Ty>::operator=(const Shared_ptr<_Ty>& rhs) //拷贝赋值
{
//处理自赋值的情况
++(*rhs.use); //先递增右侧对象引用计数
free(); //递减本对象的引用计数
///更新引用计数
use = rhs.use;
element = rhs.element;
return *this;
}
template<typename _Ty>
Shared_ptr<_Ty>& Shared_ptr<_Ty>::operator=(Shared_ptr<_Ty>&& rhs) noexcept //使用移动赋值
{
if (this != &rhs) //检查自赋值情况
{
use = rhs.use;
element = rhs.element;
rhs.element = rhs.use = nullptr; //使其进入可析构状态
}
return *this;
}
template<typename _Ty>
_Ty& Shared_ptr<_Ty>::operator*() //解引用运算符
{
return *element; //返回解引用之后的对象
}
template<typename _Ty>
const _Ty& Shared_ptr<_Ty>::operator*() const
{
return *element; //返回常量解引用
}
template<typename _Ty>
inline _Ty * Shared_ptr<_Ty>::operator->() const
{
return element;
}
template<typename _Ty>
inline void Shared_ptr<_Ty>::release()
{
free(); //调用free函数进行释放。如果当前的引用计数为1或者为0的话,那么旧内存被释放。否则只是引用计数-1
element = use = nullptr; //使指针进行安全模式,防止二次析构
}
template<typename _Ty>
inline void Shared_ptr<_Ty>::reset(_Ty * p) //使用动态指针进行重置
{
free(); //调用free函数 递减引用计数
///更新指针和引用计数
use = new int(1);
element = p;
}
template<typename _Ty>
inline void Shared_ptr<_Ty>::reset(_Ty * p, _Del d)
{
free(); //递减引用计数 必要时释放内存
use = new int(1);
element = p;
del = d; // 设置自定义删除器
}
template<typename _Ty>
inline void Shared_ptr<_Ty>::reset(const Shared_ptr<_Ty>& rhs)
{
*this = rhs; //直接可以调用赋值函数完成
}
template<typename _Ty>
inline void Shared_ptr<_Ty>::free()
{
if (--*use <= 0) { //当引用计数为0或者小于0的时候进行释放元素,小于0的情况是该类使用了默认构造或者是释放了内存
///如果用户提供了删除器的话,使用用户提供的删除器进行删除
del ? del(element) : delete element;
delete use;
std::cout << "Delete success" << std::endl; //测试语句
}
}
#endif