再学智能指针

本文介绍了智能指针的实现原理,包括计数类`u_ptr`和操作类`HasPtr`。`u_ptr`用于存储核心指针和使用计数,`HasPtr`则负责维护计数并确保在不再被引用时正确删除对象。通过这种方式,智能指针避免了野指针和重复删除的问题。示例中展示了如何使用`HasPtr`类,并在异常情况下确保资源的正确释放。
摘要由CSDN通过智能技术生成
/*
 * =====================================================================================
 *
 *       Filename:  smart_pointer.cpp
 *
 *    Description:  智能指针学习
 *			 
 *
 *        Version:  1.0
 *        Created:  08/25/2012 08:48:12 PM
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  lsff (lsff), 
 *    
 *
 * =====================================================================================
 */
#include <stdlib.h>
#include <iostream>
#include <cstdio>
using namespace std;

typedef int T;	// 共享的东西的类型

/*
 * 计数类: 存储核心指针,核心指针指向真正的数据
 *		   这个类是不做任何操作的
 *		   负责存放目前指向对象自身的指针个数及真正的指针
 */
class u_ptr
{
	friend class HasPtr; 
	size_t use;
	T* pCommon;
	u_ptr(T* pCommon):pCommon(pCommon), use(1){}
	~u_ptr() {  if(pCommon) {cout<<"delete:"<<*pCommon<<endl;delete []pCommon; }pCommon=NULL;}
	T*& operator->()
	{
		return pCommon;
	}
};

/*
 * 真正的智能指针:
 *		负责对上面的计数指针进行维护
 *			1) 这个智能指针可以像普通指针用
 *			2)保证了2个点:指针赋值和初始化(用本类指针对象)
 *							发生时,对维护的计数指针进行值复制的同时,记录了
 *							所有指向计数指针个数
 *			3)在对象的计数指针没有被其它对象指向的时候删除对象
 *		好处: 避免野指针; 避免重复delete同一地址
 *
 *  其实可以把上面的计数类看作是数据类,而本类就是操作类
 */
class HasPtr
{
	private:
		u_ptr* ptr;
	public:
		/*
		 *  注意在四大函数对 计数类的维护
		 */
		HasPtr(T* p=NULL):ptr(new u_ptr(p)){} //允许指针值为NULL
		~HasPtr() { if(ptr &&0==--(ptr->use)) delete ptr; } //
		HasPtr(const HasPtr& orig): ptr(orig.ptr){ if(ptr)++ptr->use;  } //this->().->use
		HasPtr& operator=(HasPtr& ); 

		HasPtr& operator=(T* pt);  // 让智能指针更像普通的指针
		u_ptr*& operator ->(){ return ptr;} 

		void showVal()const 
		{
			printf("ptr: %p\tptr->use:%d\tptr->pCommon:%p\t*ptr->pCommon:%d\n", ptr,ptr->use,ptr->pCommon,*(ptr->pCommon));
		}
};

HasPtr& HasPtr::operator=(HasPtr& rhs)
{
//	cout<<"this->->use:"<<(this->operator->())->use<<endl; //可以
//	cout<<"this->->use:"<<this->->use<<endl;			   //不可以
	if(rhs.ptr) ++(rhs->use);
	if(ptr&&0==--ptr->use){  delete ptr; ptr=NULL;}
	this->ptr=rhs.ptr;
	return *this;
}

HasPtr& HasPtr::operator=(T* pt)
{
	HasPtr tmp = pt;
	*this=tmp;
	return *this;
}

class tst
{
	private :
		HasPtr sp;
	public:
		tst():sp(NULL){
			sp=new T(4);
			sp.showVal();
			throw "构造函数时出错!";
		}
		~tst()
		{
			cout<<__FUNCTION__<<endl;
		}
		void show()
		{
			sp.showVal();
		}
};



int main()
{

	try{
		tst tst1;
		tst1.show();
		tst tst2=tst1;
		tst2.show();
		HasPtr hp=new T(3);
		*(hp->pCommon)=4;
	}
	catch(const char*e )
	{
		cout<<e<<endl;	  // 就算是构造函数中发生了异常,申请的堆空间也照样释放了
	}
	return 0;	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值