C++:模拟实现智能指针的unique_ptr 和 删除器

本文详细介绍了如何模拟实现C++11标准库中的unique_ptr,包括泛化和部分特化版本的删除器,以及指向单独对象和数组的智能指针。内容涵盖智能指针的构造、析构、获取删除器、解引用、资源释放、重置、交换等关键功能。此外,还展示了如何创建管理新对象的独占指针,以及实现类似C++14的make_unique功能。
摘要由CSDN通过智能技术生成

前言

在上篇文章中说到,智能指针unique_ptr的删除器有不同的特化版本,本文将模拟实现unique_ptr和它的辅助类 删除器。

一、删除器

1.泛化版本的删除器

在这个模板类中,实现其删除仿函数,实现的是delete ptr,意思就是可以删除单独的堆区对象。

template<class _Ty>
class MyDeletor
{
public:
	MyDeletor() = default;
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete ptr;
		}
	}
};

2. 部分特化版本的删除器

这个删除器的参数特化了一个类型加[ ],且在实现时使用的delete[] ptr,意思是可以接收一组对象,析构堆区的一组对象。

template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
	MyDeletor() = default;
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete[]ptr;
		}
	}
};

二、实现my_unique_ptr

(一) 泛化版本——指向单独对象的智能指针

  1. 首先,模板给出两个参数,一个是要指向的对象类型,另一个是删除器类型,这个删除器是泛化版本的删除器。
  2. 私有成员有两个,一个是指针,一个是删除器成员。
  3. 模拟unique_ptr的特性,不能拷贝构造和赋值构造,所以将这两个函数删除。
  4. 在析构函数中,如果指针不为nullptr,则调用删除器,并将指针指向nullptr。
// class 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  _myDeletor;
public:
	my_unique_ptr(const my_unique_ptr&) = delete;
	my_unique_ptr& operator=(const my_unique_ptr&) = delete;

	my_unique_ptr(pointer _P = nullptr) :_Ptr(_P) { cout << "my_unique_ptr: " << this << endl; }
	~my_unique_ptr()
	{
		if (_Ptr != nullptr)
		{
			_myDeletor(_Ptr);
			_Ptr = nullptr;
		}
		cout << "~my_unique_ptr: " << this << endl;
	}

观察器

1.获得用于析构被管理对象的删除器

两个版本:普通的和常性的

	_Dx& get_deletor()
	{
		return _myDeletor;
	}
	const _Dx& get_deletor() const
	{
		return _myDeletor;
	}

2. 获得当前指针

	pointer get() const
	{
		return _Ptr;
	}

3.重载bool运算符

operator bool() const
{
	return _Ptr != nullptr;
}

有了这个方法,就可以在各种控制语句中使用该指针。
示例:

int main(void)
{
	my_unique_ptr<int> op(new int(10));

	if (op) {
		//
	}

	op != false;
}

4.重载解引用和指向符

重载解引用符,为了获得当前指针所指向的对象;
重载指向符,是为了获得指针本身。

	_Ty& operator*() const
	{
		return *_Ptr;
	}

	pointer operator->() const
	{
		return &**this;// _Ptr; 
	}

修改器

5.释放资源函数(释放所有权)

即将资源转移给其他指针:再将自身指针置为空。

pointer release()
{
	_Ty* old = _Ptr;
	_Ptr = nullptr;
	return old;
}

6.重置指向函数(替换被管理对象)

申请一个指针指向当前指针所指向的对象;
让当前指针指向函数传递进来的参数所指向的对象;
再(调用删除器)将原来所指的对象删除。

void reset(pointer _P = nullptr)
{
	pointer old = _Ptr;
	_Ptr = _P;
	if (old != nullptr)
	{
		_myDeletor(old);
		// get_deletor()(old);
	}
}

7.交换资源的函数

直接调用系统提供的swap函数

void swap(my_unique_ptr _Y)
{
	std::swap(_Ptr, _Y._Ptr);
	std::swap(_myDeletor, _Y._myDeletor);
}

特殊的成员函数

8.移动构造和移动赋值

移动构造:将资源转移给this当前的指针。

my_unique_ptr(my_unique_ptr&& _Y)
{
	_Ptr = _Y._Ptr;
	_Y._Ptr = nullptr;
	cout << " move copy my_unique_ptr : " << this << endl;
}

移动赋值:同样是完成资源的转移

流程:

  1. 如果this指针与参数相同,则不执行,直接返回this
  2. 查看当前指针指向是否为空,不为空则调用删除器删除
  3. 将参数的资源转移给this的_Ptr,再将参数的_Ptr置为空。
  4. 返回this指针所指之物。
my_unique_ptr& operator=(my_unique_ptr&& _Y)
{
	if (this == &_Y) return *this;
	
	if (_Ptr != nullptr) { _myDeletor(_Ptr); }
	_Ptr = _Y._Ptr;
	_Y._Ptr = nullptr;
	
	cout << " move opertor=: " << endl;
	return *this;
}

实际上,上述代码可以利用已实现的函数来完成

	my_unique_ptr& operator=(my_unique_ptr&& _Y)
	{
		if (this == &_Y) return *this;
		reset(_Y.release());
		
		cout << " move opertor=: " << endl;
		return *this;
	}

(二)部分特化版本——指向一组对象的智能指针

特化版本除了模板参数有变化,其他内容和泛化版本一致。

// class unique_ptr array
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;
	_Dx  _myDeletor;

}

提供到被管理数组的有索引访问

_Ty& operator[](size_t _Idx) const
{
	return _Ptr[_Idx]; 
}

(三)创建一个管理新对象的独占指针

C++14引入make_unique<>
构造的指针可以指向 多个参数的对象,再构造时传入的参数可变。

template<class _Ty, class ..._Type>
my_unique_ptr<_Ty> my_make_unique(_Type&& ... _arys)
{
	return my_unique_ptr<_Ty>(new _Ty(_arys...));
}

三、完整代码


template<typename _Ty>
class myDeletor
{
public:
	myDeletor() = default;
	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete ptr;
		}
	}
};

template<typename _Ty>
class myDeletor<_Ty[]>
{
public:
	myDeletor() = default;

	void operator()(_Ty* ptr) const
	{
		if (ptr != nullptr)
		{
			delete[]ptr;
		}
	}
};

// my_unique_ptr
template<typename _Ty, typename _Dx = myDeletor<_Ty> >
class my_unique_ptr
{
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using delete_type = _Dx;

private:
	pointer _Ptr;
	delete_type _myDeletor;

public:
	my_unique_ptr(const my_unique_ptr& _Y) = delete;
	my_unique_ptr operator =(const my_unique_ptr& _Y) = delete;

	my_unique_ptr(pointer _P = nullptr)
		: _Ptr(_P)
	{
		cout << "my_unique_ptr: " << this << endl;
	}

	~my_unique_ptr() {
		if (_Ptr != nullptr) {
			_myDeletor(_Ptr);
			_Ptr = nullptr;
		}
		cout << "~my_unique_ptr: " << this << endl;
	}

	_Dx& get_deletor() {
		return _myDeletor;
	}
	const _Dx& get_deletor() const {
		return _myDeletor;
	}

	pointer get_pointer() const {
		return _Ptr;
	}

	operator bool() {
		return _Ptr != nullptr;
	}

	_Ty& operator*() const {
		return *_Ptr;
	}

	pointer operator->() const {
		return &**this;
	}

	pointer release() {
		pointer old = _Ptr;
		_Ptr = nullptr;

		return old;
	}

	void reset(pointer _P = nullptr) {
		pointer old = _Ptr;
		_Ptr = _P;

		if (old != nullptr) {
			_myDeletor(old);
			// get_deletor()(old);
		}
	}

	void Swap(my_unique_ptr _Y) {
		std::swap(_Ptr, _Y._Ptr);
		std::swap(_myDeletor, _Y._myDeletor);
	}

	my_unique_ptr(my_unique_ptr&& _Y) {
		_Ptr = _Y._Ptr;
		_Y = nullptr;
	}

	my_unique_ptr& operator=(my_unique_ptr&& _Y) {
		if (this == &_Y) {
			return *this;
		}

		reset(_Y.release());
		return *this;
	}

};

// array
template<typename _Ty, typename _Dx>
class my_unique_ptr<_Ty[], _Dx>
{
public:
	using pointer = _Ty*;
	using element_type = _Ty;
	using delete_type = _Dx;

private:
	pointer _Ptr;
	delete_type _myDeletor;

public:
	my_unique_ptr(const my_unique_ptr& _Y) = delete;
	my_unique_ptr operator =(const my_unique_ptr& _Y) = delete;

	my_unique_ptr(pointer _P = nullptr)
		: _Ptr(_P)
	{
		cout << "my_unique_ptr: " << this << endl;
	}

	~my_unique_ptr() {
		if (_Ptr != nullptr) {
			_myDeletor(_Ptr);
			_Ptr = nullptr;
		}
		cout << "~my_unique_ptr: " << this << endl;
	}

	_Dx& get_deletor() {
		return _myDeletor;
	}
	const _Dx& get_deletor() const {
		return _myDeletor;
	}

	pointer get_pointer() const {
		return _Ptr;
	}

	operator bool() {
		return _Ptr != nullptr;
	}

	_Ty& operator*() const {
		return *_Ptr;
	}

	pointer operator->() const {
		return &**this;
	}

	pointer release() {
		pointer old = _Ptr;
		_Ptr = nullptr;

		return old;
	}

	void reset(pointer _P = nullptr) {
		pointer old = _Ptr;
		_Ptr = _P;

		if (old != nullptr) {
			_myDeletor(old);
			// get_deletor()(old);
		}
	}

	void Swap(my_unique_ptr _Y) {
		std::swap(_Ptr, _Y._Ptr);
		std::swap(_myDeletor, _Y._myDeletor);
	}

	my_unique_ptr(my_unique_ptr&& _Y) {
		_Ptr = _Y._Ptr;
		_Y = nullptr;
	}

	my_unique_ptr& operator=(my_unique_ptr&& _Y) {
		if (this == &_Y) {
			return *this;
		}

		reset(_Y.release());
		return *this;
	}

	_Ty& operator[](size_t _Idx) const {
		return _Ptr[_Idx];
	}
};

template<typename _Ty, typename ... _Type>
my_unique_ptr<_Ty> my_make_unique(_Type&& ... _args)
{
	return my_unique_ptr<_Ty>(new _Ty(_args...));
}

end

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_索伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值