手动实现C++11的智能指针

unique_ptr

功能

unique_ptr独占资源,并使用RAII的方式管理资源。

设计思想

1)仅仅利用RAII的思想取管理资源,即类初始化时,获取资源;类析构时,释放资源;
2)并且为了保证资源独占性,禁用了拷贝函数;

源码

unique_ptr.h

#pragma once

template<typename T>
class unique_ptr {
public:
	unique_ptr()noexcept{}
	unique_ptr(T* Ptr) :_Ptr(Ptr) {}
	unique_ptr(unique_ptr&& right)noexcept {
		swap(right._Ptr, _Ptr);
	}
	unique_ptr& operator=(unique_ptr&& right) {
		if (this == &right) return *this;
		deconstruct();
		_Ptr = right._Ptr;
		right._Ptr = nullptr;
		return *this;
	}

	~unique_ptr() {
		deconstruct();
	}

	T& operator*() {
		return *_Ptr;
	}

	T* operator->() {
		return _Ptr;
	}

	T* get() {
		return _Ptr;
	}
	T* release() {
		T* old = nullptr;
		swap(_Ptr, old);
		return old;
	}

	void reset(T* Ptr = nullptr) {
		deconstruct();
		_Ptr = Ptr;
	}

private:
	unique_ptr(const unique_ptr&) = delete;
	unique_ptr& operator=(const unique_ptr&) = delete;

	void deconstruct() {
		if (_Ptr != nullptr) {
			delete _Ptr;
			_Ptr = nullptr;
		}
	}
	T* _Ptr{nullptr};
};

shared_ptr与weak_ptr

功能

1)shared_ptr共享指针,允许多个shared_ptr实例管理同一份资源;
2)weak_ptr持有资源,但不管理资源;

设计思想

1)一份资源Ptr对应一份引用计数器Ref_Count;即管理同一个资源Ptr的shared_ptr实例和weak_ptr实例,都具有同一份共享的引用计数器Ref_Count;
2)shared_ptr利用引用计数器的思想管理资源。当Ref_Count的共享计数Use减为0时,释放资源Ptr;当Ref_Count的weak弱引用计数减为0时,释放该共享的引用计数器;
3)weak_ptr可以根据Ref_Count是否为nullptr以及Ref_Count中的贡献计数Use是否为0,来判断当前是否存在可用资源Ptr;
3)在C++中的shared_ptr实际上支持传入std::make_shared,可以将资源Ptr的内存空间和引用计数器Ref_Count的内存空间一起申请,优点有两点:1. 避免异常安全问题,如new资源后,再new引用计数器Ref_Count失败的话,可能会导致资源泄漏;2. 原来的两次资源分配只需要一次,且地址可以连续(有利于缓存?);但也有一个缺点,即内存空间的延迟释放,需要等Ref_Count的计数都为0时,才会释放这块空间;

源码

ref_count.h

#pragma once
class Ref_Count {
private:
	int uses = 1;
	int weak = 1;
protected:
	virtual void destory_this() = 0;
	virtual void destory_resource() = 0;
public:


	Ref_Count() {
	}

	virtual ~Ref_Count() noexcept {}

	void incref() {
		++uses;
	}

	void incwref() {
		++weak;
	}

	void decref() {
		--uses;
		if (uses == 0) {
			destory_resource();
			decwref();
		}
	}

	void decwref() {
		--weak;
		if (weak == 0) {
			destory_this();
		}
	}

	int use_count() {
		return uses;
	}
};

template<typename T>
class Ref_count_resource :public Ref_Count {
private:
	T* res;

	void destory_this() {
		delete this;
	}

	void destory_resource() {
		delete res;
	}
public:
	Ref_count_resource(T* res_) :res(res_) {}
	Ref_count_resource(const T* res_) :res(res_) {}
};

weak_ptr.h

#pragma once
#include"ref_count.h"
#include"shared_ptr.h"
template<typename T>
class weak_ptr {
public:
	weak_ptr(){}
	weak_ptr(const shared_ptr<T>& sp):_Ptr(sp._Ptr),_Ref_count(sp._Ref_count) {
		if (_Ref_count) _Ref_count->incwref();
	}
	weak_ptr(const weak_ptr& other):_Ptr(other._Ptr), _Ref_count(other._Ref_count) {
		if (_Ref_count) _Ref_count->incwref();
	}
	weak_ptr(weak_ptr&& right){
		swap(_Ptr, right._Ptr);
		swap(_Ref_count, right._Ref_count);
	}
	~weak_ptr() {
		if (_Ref_count) _Ref_count->decwref();
	}
	weak_ptr& operator=(const weak_ptr& other) {
		if (&other == this) return *this;
		if (_Ref_count) _Ref_count->decwref();
		_Ptr = other._Ptr;
		_Ref_count = other._Ref_count;
		if (_Ref_count) _Ref_count->incwref();
	}
	weak_ptr& operator=(weak_ptr&& right) {
		if (&right == this) return *this;
		if (_Ref_count) _Ref_count->decref();
		_Ref_count = nullptr;
		_Ptr = nullptr;
		swap(_Ref_count, right._Ref_count);
		swap(_Ptr, right._Ptr);
	}
	weak_ptr& operator=(const shared_ptr<T>& sp) {
		if (_Ref_count) _Ref_count->decwref();
		_Ptr = sp._Ptr;
		_Ref_count = sp._Ref_count;
		if (_Ref_count) _Ref_count->incwref();
		return *this;
	}

	shared_ptr<T> lock() {
		if (expire()) return shared_ptr<T>();
		return shared_ptr<T>(_Ptr, _Ref_count);
	}

	bool expire() {
		return !_Ref_count || _Ref_count->use_count() == 0;
	}

	int use_count() {
		if (_Ref_count) return _Ref_count->use_count();
		return 0;
	}

private:
	T* _Ptr{ nullptr };
	Ref_Count* _Ref_count{ nullptr };
};

shared_ptr.h

#pragma once
#include"ref_count.h"
template <typename T>
class weak_ptr;

template<typename T>
class shared_ptr {
private:
	shared_ptr(T* Ptr, Ref_Count* Ref_count):_Ptr(Ptr),_Ref_count(Ref_count) {
		if(_Ref_count)
			_Ref_count->incref();
	}
public:
	shared_ptr()noexcept{}
	shared_ptr(T* Ptr) :_Ptr(Ptr), _Ref_count(new Ref_count_resource<T>(Ptr)) {}
	shared_ptr(const shared_ptr& other) :_Ptr(other._Ptr), _Ref_count(other._Ref_count) {
		if(_Ref_count)
			_Ref_count->incref();
	}
	shared_ptr(shared_ptr&& right){
		swap(_Ptr, right._Ptr);
		swap(_Ref_count, right._Ref_count);
	}
	~shared_ptr() { 
		if(_Ref_count)
			_Ref_count->decref();
	}

	shared_ptr& operator=(const shared_ptr& other) {
		if (&other ==this) return *this;
		if (_Ref_count) _Ref_count->decref();
		_Ref_count = other._Ref_count;
		_Ptr = other._Ptr;
		if(_Ref_count) _Ref_count->incref();
		return *this;
	}
	shared_ptr& operator=(shared_ptr&& right) {
		if (&right == this) return *this;
		if(_Ref_count) _Ref_count->decref();
		_Ref_count = nullptr;
		_Ptr = nullptr;
		swap(_Ref_count, right._Ref_count);
		swap(_Ptr, right._Ptr);
	}

	int use_count() {
		if (_Ref_count) return _Ref_count->use_count();
		return 0;
	}

	bool unique() {
		return !_Ref_count || _Ref_count->use_count() == 1;
	}

	T& operator*() {
		return *_Ptr;
	}
	T* operator->() {
		return _Ptr;
	}

	T* get() {
		return _Ptr;
	}

private:

	T* _Ptr{nullptr};
	Ref_Count* _Ref_count{nullptr};

	friend weak_ptr<T>;
};


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值