C++_智能指针的基本原理

智能指针的核心思想是将资源(内存)与指针对象的生命周期绑定起来,创建对象的同时立即为其分配资源,对象销毁时立即释放资源。
1、智能指针和资源的绑定
将裸指针和它相关的操作封装成一个类,并在创建对象时必定要调用的构造函数中,分别进行资源的分配和释操作。当然,为了保证对象的操作方式看起来与裸指针相同,这个封装类起码还要重载operator->和operator *
一个简单的,在其生命周期中绑定了一个资源的智能指针类模板My_ptr代码如下:

#include<iostream>
using namespace std;
template<class T>
class My_ptr
{
private:
	T* _ptr;    //裸指针
public:
	My_ptr(T* p):_ptr(p)
	{
		cout << "生成获得资源" << endl;
	}
	T& operator*()    //重载*运算符
	{
		return *_ptr;
	}
	T* operator->()      //重载->运算符
	{
		return _ptr;
	}
	~My_ptr()
	{
		cout << "死前释放资源" << endl;
		//delete _ptr;
	}
};
//测试代码
int main()
{
	int a = 100;
	{
		My_ptr<int> p(&a);       //指针对象p生命期开始
		cout << "打印资源数据" << *p << endl;
	}                           //指针对象p生命周期结束
	cout << "指向对象p生命周期已结束" << endl;
	return 0;
}
//输出结果如下:
生成获得资源
打印资源数据100
死前释放资源
指向对象p生命

在程序设计实践中常常需要多个指针指向(共享)同一个资源,这时,资源的释放就不能单纯地取决于某一个指针对象的生命期。既不能在还有指针使用资源的时候其他指针擅自释放资源,也不能在都不需要资源时没有即时释放资源。
目前,采用指针计数器作为资源管理者,是实现这种智能指针的一种通用实现技术。资源使用者以令计数值加1的方式向管理者登记,以减1的方式进行注销,当计数器值为0时,由管理者进行释放资源

template<typename T>
class Res_Ptr
{
private:
	T* res_p;      //指向资源的指针
	int use_num;         //计数器
	//构造函数
	Res_Ptr(int *p):res_p(p),use_num(1){}
	~Res_Ptr
	{
		delete res_p;
	}
	friend class SharedPtr;   
};

类中以友元类的方式指定了资源使用者的所属类SharePtr。由于这个类的析构函数仅完成了资源释放工作,所以使用者类除了在构造函数中为计数器加1之外,还必须在其析构函数中为计数器减1,并判断是否应该释放资源

template<typename T>
class SharePtr
{
public:
	//构造函数
	SharePtr(T* p, T i): ptr(new Res_Ptr<T>(p)), val(i){}
	//复制构造函数
	SharePtr(const SharePtr& orig) :ptr(orig.ptr), val(orig.val)
	{
		++ptr->use_num;    //指向同一资源指针对象数目加1
	}
	~SharePtr()
	{
		if (--ptr->use_num == 0)   //析构一个指针对象,计数器减去1
			delete ptr;     //如果计数器为0,则删除资源对象
	}
private:
	Res_Ptr<T>* ptr;       //指向资源对象Res_Ptr的指针
	T val;       //可以修改资源数据的变量
};

将上面两个类连起来编写一个程序

#include<iostream>
using namespace std;
template<typename T> class SharePtr;
template<typename T>
//定义计数类模板
class Res_Ptr
{
	friend class SharePtr<T>;
private:
	T* res_p;      //指向资源的指针
	int use_num;         //计数器
	//构造函数
	Res_Ptr(int *p):res_p(p),use_num(1)
	{
		cout << "Res_Ptr构造函数" << endl;
	} 
	~Res_Ptr()
	{
		delete res_p;
		cout << "Res_Ptr析构函数" << endl;
	} 
};
//SharePtr模板声明
template<typename T>
class SharePtr
{
public:
	//构造函数
	SharePtr(T* p, T i): ptr(new Res_Ptr<T>(p)), val(i)
	{
		cout << "SharePtr构造函数" << "use_num = " << ptr->use_num << endl;
	}
	//复制构造函数
	SharePtr(const SharePtr& orig) :ptr(orig.ptr), val(orig.val)
	{
		++ptr->use_num;    //指向同一资源指针对象数目加1
		cout << "SharePtr复制构造函数" << "use_num = " << ptr->use_num << endl;
	}
	~SharePtr()
	{
		cout << "SharePtr析构函数" << "use_num = " << ptr->use_num << endl;
		if (--ptr->use_num == 0)   //析构一个指针对象,计数器减去1
			delete ptr;     //如果计数器为0,则删除资源对象
	}
private:
	Res_Ptr<T>* ptr;       //指向资源对象Res_Ptr的指针
	T val;       //可以修改资源数据的变量
};
//测试代码
int main()
{
	{
		SharePtr<int>hpa = SharePtr<int>(new int(42), 100);    //构造第一个指针对象,指向资源为整型数据42
		{
			SharePtr<int>hpb(hpa);   //复制构造指针对象
			SharePtr<int>hpc(hpb);
			SharePtr<int>hpd = hpa;
		};
		cout << "内层括号结束" << endl;
	}
	cout << "中层括号结束" << endl;
	return 0;
}
//输出结果
Res_Ptr构造函数
SharePtr构造函数use_num = 1
SharePtr复制构造函数use_num = 2
SharePtr复制构造函数use_num = 3
SharePtr复制构造函数use_num = 4
SharePtr析构函数use_num = 4
SharePtr析构函数use_num = 3
SharePtr析构函数use_num = 2
内层括号结束
SharePtr析构函数use_num = 1
Res_Ptr析构函数
中层括号结束

在C++11的标准中也定义了三大智能指针,uniquer_ptr、shared_ptr和weak_ptr,具体使用方式可以参考C++ Primer 5th

发布了65 篇原创文章 · 获赞 4 · 访问量 1017

猜你喜欢

转载自blog.csdn.net/CLZHIT/article/details/103653823
今日推荐