智能指针的模拟实现 auto_ptr scoped_ptr shared_ptr

RAII(Resource Acquisition Is Initialization)
ide

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

智能指针:用自动化或者说智能的指针来实现对动态内存的释放。它是一个类,有相似指针的功能。ui

常见的智能指针:auto_ptr/scoped_ptr/scoped_array/shared_ptr/shared_array,因为scoped_array和scoped_ptr比较相似,shared_array和shared_ptr又比较相似,因此咱们只实现auto_ptr/scoped_ptr/shared_ptr。this

1、auto_ptrspa

最开始auto_ptr的成员变量主要有T* _ptr,bool _owner,主要实现原理是在构造对象时赋予其管理空间的全部权,在析构函数中经过_owner的真否来释放全部权,而且在拷贝或赋值后经过将_owner设为false,转移空间的全部权。具体实现代码以下:指针

template <typename T>
class AutoPtr
{
public:
	AutoPtr(T* ptr = NULL);
	AutoPtr(AutoPtr<T>& ap);
	AutoPtr<T>& operator=(AutoPtr<T>& ap);
	~AutoPtr();
	T& operator*()const;
	T* operator->()const;
	T* GetStr()const;
protected:
	T* _ptr;
	bool _owner;
};

template <typename T>
AutoPtr<T>::AutoPtr(T* ptr) : _ptr(ptr), _owner(true)
{}

template <typename T>
AutoPtr<T>::AutoPtr(AutoPtr<T>& ap) : _ptr(ap._ptr), _owner(true)
{
	ap._owner = false;
}

template <typename T>
AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap)
{
	if (this != &ap)
	{
		delete this->_ptr;
		this->_ptr = ap._ptr;
		this->_owner = true;
		ap._owner = false;
	}
	return *this;
}

template <typename T>
AutoPtr<T>::~AutoPtr()
{
	if (this->_ptr)
	{
		this->_owner = false;
		delete this->_ptr;
	}
}

template <typename T>
T& AutoPtr<T>::operator*()const
{
	return *(this->_ptr);
}

template <typename T>
T* AutoPtr<T>::operator->()const
{
	return this->_ptr;
}

template <typename T>
T* AutoPtr<T>::GetStr()const
{
	return (this->_ptr);
}

主要问题:若是拷贝出来的对象比原来的对象出做用域,则原来的对象的_owner虽然为false,但却课访问一块已经释放的一块空间。对象

auto_ptr的第二种实现方法:仍是管理空间的全部权转移,但这种实现方法中没有_owner。构造和析构和上述实现方法相似,但拷贝和赋值后直接将_ptr赋为空,禁止其在访问原来的内存空间。具体代码以下:内存

template <typename T>
class AutoPtr
{
public:
	AutoPtr();
	AutoPtr(T* ptr);
	AutoPtr(AutoPtr<T>& ap);
	AutoPtr<T>& operator=(AutoPtr<T>& ap);
	~AutoPtr();
	T& operator*()const; 
	T* operator->()const;
	T* GetStr()const;
protected:
	T* _ptr;
};

template <typename T>
AutoPtr<T>::AutoPtr() : _ptr(NULL)
{}

template <typename T>
AutoPtr<T>::AutoPtr(T* ptr) : _ptr(ptr)//不能写成const T* ptr,由于不然为const类型的赋值给非const类型
{}

template <typename T>
AutoPtr<T>::AutoPtr(AutoPtr<T>& ap) : _ptr(ap._ptr)
{
	ap._ptr = NULL;
}

template <typename T>
AutoPtr<T>& AutoPtr<T>::operator=(AutoPtr<T>& ap)
{
	if (this != &ap)
	{
		delete this->_ptr;
		this->_ptr = ap._ptr;
		ap._ptr = NULL;
	}
	return *this;
}

template <typename T>
AutoPtr<T>::~AutoPtr()
{
	if (this->_ptr)
	{
		delete this->_ptr;
	}
}

template <typename T>
T& AutoPtr<T>::operator*()const
{
	return *(this->_ptr);
}

template <typename T>
T* AutoPtr<T>::operator->()const
{
	return this->_ptr;
}

template <typename T>
T* AutoPtr<T>::GetStr()const
{
	return (this->_ptr);
}

2、scoped_ptr资源

scoped_ptr的实现原理是防止对象的拷贝与赋值。具体实现是将拷贝构造函数和赋值运算符重载函数设置为保护或私有,而且只声明不实现,设置为保护或私有是防止他人在类外本身实现。具体代码以下:作用域

template <typename T>
class ScopedPtr
{
public:
	ScopedPtr(T* ptr = NULL);
	~ScopedPtr();
	T* operator->()const;
	T& operator*()const;
	T* GetPtr()const;
protected:
	ScopedPtr(const ScopedPtr<T>& ptr);
	ScopedPtr<T>& operator=(const ScopedPtr<T>& ptr);
protected:
	T* _ptr;
};

template <typename T>
ScopedPtr<T>::ScopedPtr(T* ptr) :_ptr(ptr)
{}

template <typename T>
ScopedPtr<T>::~ScopedPtr()
{
	if (this->_ptr)
	{
		delete this->_ptr;
	}
}

template <typename T>//应用于类型为结构体时
T* ScopedPtr<T>::operator->()const
{
	return this->_ptr;
}

template <typename T>
T& ScopedPtr<T>::operator*()const
{
	return *(this->_ptr);
}

template <typename T>
T* ScopedPtr<T>::GetPtr()const
{
	return (this->_ptr);
}

shared_ptr的实现及相关问题见下篇博客。

相关文章
相关标签/搜索