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

RAII(Resource Acquisition Is Initialization)

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

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

常见的智能指针:auto_ptr/scoped_ptr/scoped_array/shared_ptr/shared_array,由于scoped_array和scoped_ptr比较类似,shared_array和shared_ptr又比较类似,所以我们只实现auto_ptr/scoped_ptr/shared_ptr。

一、auto_ptr

最开始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);
}

二、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的实现及相关问题见下篇博客。

你可能感兴趣的:(C++,auto,智能指针)