智能指针auto_ptr,unique_ptr(附详细代码)

智能指针

RAII :资源获取(初始化)->使用局部对象来管理资源的技术称为资源获取

          RAII原理:三步骤

  1. 获取资源(创建对象),不限制于对资源,还包括线程,套接字,互斥量,句柄等
  2. 使用资源
  3. 销毁资源(析构对象)

让资源自动销毁的方案—>RAll—>利用C++局部对象自动销毁的特性

裸指针: 直接定义的指针à无法判断裸指针定义的是一个对象还是一组对象

裸指针的问题

          

野指针:未被初始化的指针

空指针:初始化为空的指针

悬空/失效指针:使用后被释放的指针  (free,delete)

auto_ptr 该智能指针已经在C11中被移除,原因:

1.该智能指针无法判别指向的是一组对象还是一个对象

2.意义不明确,在赋值时,不确定是a,b对象共享资源还是将b对象转移给a对象

auto_ptr代码:

template<class _Ty>
class my_auto_ptr
{
private:
	bool _Owns;//拥有权为真时,ptr指向所拥有对象
	_Ty* _Ptr;
public:
	typedef _Ty element_type;
	//explicit 用于构造函数,防止隐式转换-->
	/*
	(构造函数只有一个参数,若用=10直接传参,会存在一个缺省的转换操作
	    改构造函数会将对应的数据转换为该类对象)
	*/
	explicit my_auto_ptr(_Ty *p=0): _Owns(_p!=0),_ptr(_p){}//构造函数
	~my_auto_ptr()//析构函数
	{
		if (_Owns) { delete _Ptr; };
		_Owns = false;
		_Ptr = NULL;
	}
	_Ty* get()const { return _Ptr };//得到指针
	 
	_Ty& operator*()const//重载*
	{
		return *(get());
	}
	_Ty* operator->()const//重载指向符
	{
		return get();//return &**this;//
	}
	void reset(_Ty* p)//重置
	{
		if (_Owns)
		{
			delete _Ptr;
		}
		_Ptr = p;
	}
	//release() 释放函数 ,不明确是资源的转移还是资源的共享
};
/*
auto 指针拷贝构造函数,若使用浅拷贝,两个对象共享资源,会对同一个堆空间释放两次
 若使用深拷贝,将自己的拥有权转移给其它对象,当该对象被销毁时,自己同时也会失去堆对象的拥有权
 同时,由于auto_ptr无法确认自己指向的是哟个对象还是一组对象,因此在C11之后被移除
 */

void fun()
{
	my_auto_ptr<Object> obj(new Object(10));

	cout << obj->Value() << endl;//重载指向符后返回的是Obj类型_Ptr指针,通过该指针指向Value方法
	cout << (*obj).Value() << endl;//重载*  返回 *_Ptr(所指之物)(同时以引用返回),此时出现了一个所指之物的别名,利用其别名调动Value函数
    
}

unique_ptr 解决了上述auto_ptr的问题,利用模板参数区分了是指向一个对象还是一组对象

unique_ptr 的默认删除器

template<class _Ty>
class MyDeletor
{
public: 
	MyDeletor() = default;//C11中新概念  默认构造函数,目的性更强更明确
	//MyDeletor() {} 默认构造函数
	//类似于delete   Object(const Object&)=delete;---》删除拷贝构造函数
	//重写( );即重写对函数的调用 
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete ptr;//使用delete 先调用析构函数,在释放空间;
		}
	}
};

template<class _Ty>
class MyDeletor<_Ty[]>//部分特化
{
public:
	MyDeletor() = default;
	void operator()(_Ty* ptr)const
	{
		if (ptr != nullptr)
		{
			delete[]ptr;//删除一组对象
		}
	}
};

unique_ptr总代码:


//default_delete  unique_ptr的默认删除器
#ifndef MY_UNIQUE_PTR_H  //如果不存在,则#define,若存在,则#end
#define MY_UNIQUE_PTR_H

template<class _Ty>
class MyDeletor
{
public: 
	MyDeletor() = default;//C11中新概念  默认构造函数,目的性更强更明确
	//MyDeletor() {} 默认构造函数
	//类似于delete   Object(const Object&)=delete;---》删除拷贝构造函数
	//重写( );即重写对函数的调用 
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete ptr;//使用delete 先调用析构函数,在释放空间;
		}
	}
};

template<class _Ty>
class MyDeletor<_Ty[]>//部分特化
{
public:
	MyDeletor() = default;
	void operator()(_Ty* ptr)const
	{
		if (ptr != nullptr)
		{
			delete[]ptr;//删除一组对象
		}
	}
};

//my_unique_ptr
template<class _Ty,class _Dx=MyDeletor<_Ty>>
class my_unique_ptr
{
public:
	using pointer = _Ty*;          //typedef _Ty* pointer
	using element_type = _Ty;      //typedef _Ty  element_type;
	using delete_type = _Dx;       //typedef _Dx delete_type;
private:
	_Ty* _Ptr;
	_Dx _myDletetor;
public:
	my_unique_ptr(pointer _p =nullptr):_Ptr(_p){}
	~my_unique_ptr()
	{
		if (_Ptr != nullptr)
		{
			_myDletetor(_Ptr);//释放其空间
			_Ptr = nullptr;
		}
	}
	//由于二义性,删除拷贝构造函数和赋值函数
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	//移动拷贝函数
	my_unique_ptr(my_unique_ptr&& _Y)
	{
		_Ptr = _Y._Ptr;
		_Y._Ptr = nullptr;
	}
	//移动赋值
	my_unique_ptr& operator=(my_unique_ptr&& _Y)
	{
		if (this == &_Y) return *this;
		reset(_Y.release());
		return *this;
	}
	pointer release()//释放this指针资源,
	{
		_Ty* old = _Ptr;
		_Ptr = nullptr;
		return old;
	}
	void reset(pointer _P=nullptr)//重置资源
	{
		pointer old = _Ptr;
		_Ptr = _P;
		if (old != nullptr)
		{
			_myDletetor(old);
		}
	}
	//获得当前对象的删除器
	_Dx& get_deleter()
	{
		return _myDletetor;
	}
	const _Dx& get_deleter()const
	{
		return _myDletetor;
	}
	//重载
	_Ty& operator*()const
	{
		return *_Ptr;
	}
	pointer operator->()const
	{
		return &**this;//返回了一个对象的地址
	}
	//获得当前指针
	pointer get_pionter()const
	{
		return _Ptr;
	}
	//为了方便判断当前指针是否有效,重载了一个bool类型的强制转换
	operator bool()const
	{
		return _Ptr != nullptr;
	}
	//资源的交换
	void swap(my_unique_ptr _Y)
	{
		std::swap(_Ptr, _Y._Ptr);
		std::swap(_myDletetor, _Y._myDletetor);
	}
	//重写一个赋值函数,将子指针强转为父类型指针
	template<class _Uy>
	my_unique_ptr& operator=(_Uy* _p)
	{
		if (this->_Ptr == (_Ty*)_p) return *this;
		if (_Ptr != nullptr) { _myDletetor(_Ptr); }
		_Ptr = _p;
		return *this;
	}
};

template<class _Ty,class _Dx>
class my_unique_ptr<_Ty[], _Dx>//特化版本,一组对象
{
public:
	using pointer = _Ty*;          //typedef _Ty* pointer
	using element_type = _Ty;      //typedef _Ty  element_type;
	using delete_type = _Dx;       //typedef _Dx delete_type;
private:
	_Ty* _Ptr;
	_Ty _myDletetor;
public:
	my_unique_ptr(pointer _p = nullptr) :_Ptr(_p) {}
	~my_unique_ptr()
	{
		if (_Ptr != nullptr)
		{
			_myDletetor(_Ptr);//释放其空间
			_Ptr = nullptr;
		}
	}
	//由于二义性,删除拷贝构造函数和赋值函数
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;
	//移动拷贝函数
	my_unique_ptr(my_unique_ptr&& _Y)
	{
		_Ptr = _Y._Ptr;
		_Y._Ptr = nullptr;
	}
	//移动赋值
	my_unique_ptr& operator=(my_unique_ptr&& _Y)
	{
		if (this == &_Y) return *this;
		reset(_Y.release());
		return *this;
	}
	pointer release()//释放this指针资源,
	{
		_Ty* old = _Ptr;
		_Ptr = nullptr;
		return old;
	}
	void reset(pointer _P = nullptr)//重置资源
	{
		pointer old = _Ptr;
		_Ptr = _P;
		if (old != nullptr)
		{
			_myDletetor(old);
		}
	}
	//获得当前对象的删除器
	_Dx& get_deleter()
	{
		return _myDletetor;
	}
	const _Dx& get_deleter()const
	{
		return _myDletetor;
	}
	//重载下标运算符
	_Ty& operator[](size_t _Idx) const
	{
		return _Ptr[_Idx];
	}
	//获得当前指针
	pointer get()const
	{
		return _Ptr;
	}
	//为了方便判断当前指针是否有效,重载了一个bool类型的强制转换
	operator bool()const
	{
		return _Ptr != nullptr;
	}
	//资源的交换
	void swap(my_unique_ptr _Y)
	{
		std::swap(_Ptr, _Y._Ptr);
		std::swap(_myDletetor, _Y._myDletetor);
	}
	//重写一个赋值函数,将子指针强转为父类型指针
	template<class _Uy>
	my_unique_ptr& operator=(_Uy* _p)
	{
		if (this->_Ptr == (_Ty*)_p) return *this;
		if (_Ptr != nullptr) { _myDletetor(_Ptr); }
		_Ptr = _p;
		return *this;
	}
};
//重写一个make外部函数
template<class _Ty, class ..._Type>//..._Type 多个类型的可变参
my_unique_ptr<_Ty> my_make_ptr(_Type&&... _arrys)
{
	return my_unique_ptr <_Ty>(new _Ty(_arrys...));//构建多个参数的_Ty类
							//new Object(12)
							//new Object(12,23.3)
}

#endif


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值