智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr相关的知识,希望对你有一定的参考价值。

    RAII(Resource Acquisition Is Initialization)

资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。

所谓智能指针就是智能/自动化的管理指针所指向的动态资源的释放。

STL--auto_ptr

Boost库的智能指针(ps:新的C++11标准中已经引入了unique_ptr/shared_ptr/weak_ptr)

常见的智能指针有:auto_ptr/scoped_ptr/scoped_array/shared_ptr/shared_array。

下面介绍三种智能指针auto_ptr,scoped_ptr,shared_ptr。

//智能指针AutoPtr
template<class T>
class AutoPtr
{
public:
	AutoPtr(T* ptr)
		:_ptr(ptr)
	{}
	AutoPtr(AutoPtr<T> &ap)
		:_ptr(ap._ptr)
	{//拷贝后将原有指向同一块内存的指针置空
		ap._ptr = NULL;
	}
	AutoPtr<T>& operator=(AutoPtr<T> &ap)
	{
		if (this != &ap)
		{
			delete _ptr;
			_ptr = ap._ptr;
			ap._ptr = NULL;
		}
		return *this;
	}
	~AutoPtr()
	{
		cout << "~AutoPtr()" << endl;
		if (_ptr)
		{
			delete _ptr;
			_ptr = NULL;
		}
	}
private:
	T* _ptr;
};

//智能指针ScopedPtr
template<class T>
class ScopedPtr
{
public:
	ScopedPtr(T* ptr)
	    :_ptr(ptr)
	{}
	~ScopedPtr()
	{
		cout << "~ScopedPtr()" << endl;
		if (_ptr)
		{
			delete _ptr;
			_ptr = NULL;
		}
	}
protected://防拷贝:此处为privated或protecte;拷贝构造和赋值函数只声明不定义
	ScopedPtr(const ScopedPtr<T> &sp);
	ScopedPtr<T>& operator==(const ScopedPtr<T> &sp);
private:
	T* _ptr;
};

//智能指针SharedPtr
template<class T>
class SharedPtr
{
public:
	SharedPtr()
		:_ptr(NULL)
		, _pCount(new long(1))
	{}
	SharedPtr(T* ptr)
		:_ptr(ptr)
		, _pCount(new long(1))
	{}
	//----引用计数浅拷贝
	SharedPtr(const SharedPtr<T> &sp)
		:_ptr(sp._ptr)
		, _pCount(sp._pCount)
	{
		++(*_pCount);
	}
	SharedPtr<T>& operator=(const SharedPtr<T> &sp)
	{
		if (this != &sp)
		{
			Release();
			_ptr = sp._ptr;
			_pCount = sp._pCount;
			++(*_pCount);
		}
		return *this;
	}
	////用深拷贝
	////传统写法
	//SharedPtr<T>& operator=(const SharedPtr<T>& sp)
	//{
	//	if (this != &sp)
	//	{
	//		SharedPtr<T> tmp(sp);
	//		swap(_ptr, tmp._ptr);
	//		swap(_pCount, tmp._pCount);
	//	}
	//	return *this;
	//}
	//现代写法
	//SharedPtr<T>& operator=(SharedPtr<T> sp)
	//{
	//	swap(_ptr, sp._ptr);
	//	swap(_pCount, sp._pCount);
	//	return *this;
	//}
	~SharedPtr()
	{
		cout << "~SharedPtr()" << endl;
		Release();
	}
	T& operator*()
	{
		return *_ptr;
	}
	T* GetPtr()//返回原指针_ptr
	{
		return  _ptr;
	}
	T* operator->()
	{
		return _ptr;
	}
	long GetCount()//返回同一内存的指向数
	{
		return *_pCount;
	}
	void Release()//释放内存
	{
		if (--(*_pCount) == 0)
		{
			delete _ptr;
			delete _pCount;
			_ptr = NULL;
			_pCount = NULL;
		}
	}
private:
	T* _ptr;
	long* _pCount;
};

测试用例如下:

void  Test()
{
	AutoPtr<int> ap1(new int(3));
	AutoPtr<int> ap2 = ap1;
	AutoPtr<int> ap3(new int(5));
	ap3 = ap2;

	ScopedPtr<int> sp1(new int(3));
	//防拷贝
	//ScopedPtr<int> sp2 = sp1;
	//sp2 = sp1;

	SharedPtr<int> shp1(new int(3));
	SharedPtr<int> shp2 = shp1;
	SharedPtr<int> shp3(new int(5));
	shp3 = shp1;
	*shp1 = 6;
	cout << &shp1 << endl;
	cout << shp1.GetCount() << endl;
	cout << *(shp1.GetPtr()) << endl;//输出_ptr的值
	cout << *(shp1.operator->()) << endl;//输出_ptr的值
}

模板的分离编译

1、在模板头文件 xxx.h 里面显示实例化->模板类的定义后面添加 template class SeqList<int >; 一般不推荐这种方法,一方面老编译器可能不支持,另一方面实例化依赖调用者。(不推荐)

2、将声明和定义放到一个文件 "xxx.hpp" 里面,推荐使用这种方法。

本文出自 “Materfer” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1753272

以上是关于智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr的主要内容,如果未能解决你的问题,请参考以下文章

智能指针:模拟实现auto_ptr,scoped_ptr,shared_ptr

智能指针之auto_ptr和scoped_ptr

智能指针(模拟实现auto_ptr,shared_ptr,scooeptr 以及定制删除器c++ 实现)

C++智能指针详解:scoped_ptr

智能指针的模拟实现shared_ptr 循环引用 定置删除器

scoped _ptr的模拟实现与解析