智能指针不是指针,是对象,但是当作指针来用。
原理:对每个所指目标保存一个额外的引用计数,使多个指针可以动态的共享所指对象,即指向一个对象的指针可以增加和减少,当且仅当对象的引用计数为0时才由智能指针调用delete,释放堆上的内存。
思路:交给系统来释放内存。智能指针在栈上,所指对象在堆上,系统自动对栈的对象调用析构函数,这时再由智能指针在析构函数里delete,就可以安全释放内存。
tips:引用计数不能是成员变量也不能是堆上开辟的空间,而是静态变量,存储映射关系。
具体实现:
#include <iostream>
#include <unordered_map>
using namespace std;
template<class value_type>//模版,所指之物类型
class my_ptr
{
public:
//默认构造函数
my_ptr():ptr(nullptr){}
//所指之物指针的构造函数
my_ptr(value_type *aim):ptr(aim){mapping[aim] += 1;}
//拷贝构造函数
my_ptr(const my_ptr<value_type> &other):ptr(other.ptr){mapping[ptr] += 1;}
~my_ptr()
{
if (nullptr == ptr) return;//无效指针
mapping[ptr] -= 1;//引用计数-1
if (0 == mapping[ptr])//再无指针所指向,该释放内存了
{
mapping.erase(mapping.find(ptr));//清除映射关系
delete ptr;
ptr = nullptr;
}
}
my_ptr<value_type> &operator=(const my_ptr &other)//赋值函数
{
if (&other != this)//判断自赋值情况
{
this->~my_ptr();//先主动析构,移除之前的指向
ptr = other.ptr;
mapping[ptr] += 1;
}
return *this;
}
value_type *operator->() {return ptr;}//当指针来用,重载->
value_type &operator*() {return *ptr;}//当指针来用,重载*
private:
value_type *ptr;
static unordered_map<value_type *, int> mapping;
};
//静态变量在类外初始化
template<class value_type>
typename unordered_map<value_type *, int> my_ptr<value_type>::mapping;
int main()
{
int *aim = new int(1);
my_ptr<int> p1(new int(2));
my_ptr<int> p2(aim);
my_ptr<int> p3(aim);
my_ptr<int> p4(p3);
p1 = p4;
*p1 = 233;
return 0;
}