C++11__共享型智能指针的一种靠谱的简单实现

C++11__共享型智能指针的一种靠谱的简易实现

  实现共享型智能指针的关键在于共享计数,这里利用资格资源管理类实现共享计数的相关操作。

一、实现代码
  以下代码提供了一种规范的共享型智能指针简单实现,注释应该比较清楚。

#pragma once
#include<utility>//std::swap

//资源管理类
class SharedCount
{
public:
	SharedCount() noexcept : _count(1) {}//资源取得时便是初始化时机
	void AddCount() {
		++_count;
	}
	//Redeuce需要有返回值,便于智能指针类析构函数使用
	long ReduceCount()noexcept {
		return --_count;
	}
	//获取计数
	long GetCount() const noexcept{
		return _count;
	}
private:
	long _count;
};

template<typename T>
class SmartPtr {
public:
	//模板的各个实例之间不具有friend关系,因而不能互访私有成员
	//需要显示声明友元
	template<typename U>
	friend class SmartPtr;

	//构造函数,不支持参数隐式转换
	explicit SmartPtr(T* ptr = nullptr):_ptr(ptr) 
	{
		if (_ptr) {
			_shared_count = new SharedCount();
			std::cout << "Defult Constructor! " << *_ptr << std::endl;
		}
		else std::cout << "Defult Constructor!(nullptr) "<< std::endl;

	}

	//拷贝构造,必须有非泛型版本,防止编译器自动生成缺省版本
	SmartPtr(const SmartPtr& oth)
	{
		_ptr = oth._ptr;
		if (_ptr) {
			oth._shared_count->AddCount();
			_shared_count = oth._shared_count;
			std::cout << "Copy Constructor! " << *_ptr << std::endl;
		}
		else std::cout << "Copy Constructor!(nullptr) " << std::endl;
		
	}

	//析构函数
	~SmartPtr() 
	{
		//如果_ptr不为空且计数为0,则delete
		if (_ptr && !_shared_count->ReduceCount())
		{
			std::cout << "Destructor! " << *_ptr << std::endl;
			delete _ptr;
			delete _shared_count;	
		}
		else std::cout << "Destructor!(nullptr) " << std::endl;
	}

	//移动构造
	template<typename U>
	SmartPtr(SmartPtr<U>&& oth)
	{
		_ptr = oth._ptr;
		if (_ptr) {
			_shared_count = oth._shared_count;
			oth._ptr = nullptr;
			std::cout << "Move Constructor! " << *_ptr << std::endl;
		}
		else std::cout << "Move Constructor!(nullptr) " << std::endl;

	}

	//泛型版本拷贝构造
	template<typename U>
	SmartPtr(const SmartPtr<U>& oth)
	{
		_ptr = oth._ptr;
		if (_ptr) {
			oth._shared_count->AddCount();
			_shared_count = oth._shared_count;
			std::cout << "Template Copy Constructor! " << *_ptr << std::endl;
		}
		else std::cout << "Template Copy Constructor!(nullptr) " << std::endl;
	}

	template<typename U>
	SmartPtr(const SmartPtr<U>& oth,T* ptr) noexcept
	{
		_ptr = oth._ptr;
		if (_ptr) {
			oth._shared_count->AddCount();
			_shared_count = oth._shared_count;
		}
	}
	//重载赋值,pass by value,传递副本(常用技巧)
	SmartPtr& operator=(SmartPtr rhs) noexcept
	{
		rhs.Swap(*this);//交换副本和*this
		return *this;
	}

	void Swap(SmartPtr& rhs) noexcept
	{
		using std::swap;
		swap(_ptr, rhs._ptr);
		swap(_shared_count, rhs._shared_count);
	}

	T* Get() const noexcept
	{
		if (_ptr) return _ptr;
		else return nullptr;
	}

	long UseCount() const noexcept
	{
		if (_ptr) {
			return _shared_count->GetCount();
		}
		else return 0;
	}

	T& operator*() const noexcept
	{
		return *_ptr;
	}

	T* operator->() const noexcept
	{
		return _ptr;
	}


private:
	T* _ptr;
	SharedCount* _shared_count;
};
//全局的智能指针对象Swap
template <typename T>
void Swap(SmartPtr<T>& lhs,SmartPtr<T>& rhs) noexcept
{
	lhs.Swap(rhs);
}

//简易版本二
template<typename T>
struct newFree {
	void operator()(T* ptr) {
		if (ptr != nullptr) {
			delete ptr;
			ptr = nullptr;
		}
	}
};

template<typename T>
struct mallocFree {
	void operator()(T* ptr) {
		if (ptr != nullptr) {
			free(ptr);
			ptr = nullptr;
		}
	}
};

template<typename T, typename DF = newFree<T>>
class Sptr {
private:
	T* ptr_;
	mutex mtx_;
	int* cnt_;

public:
	Sptr(T* ptr = nullptr):ptr_(ptr) {
		unique_lock<mutex> lock(mtx);
		if (ptr != nullptr) {
			cnt_ = new int(1);//RAII
		}
	}

	Sptr(const Sptr& sp) {
		ptr_ = sp.ptr_;
		cnt_ = sp.cnt_;
		unique_lock<mutex> lock(mtx);
		if (ptr_) {
			++(*cnt_);
		}
	}

	~Sptr() {
		unique_lock<mutex> lock(mtx);
		if (ptr_) {
			DF()(ptr_);
			delete cnt_;
			cnt_ = nullptr;
		}
	}

	//pass by value
	Sptr& operator=(Sptr sp) {
		sp.Swap(*this);
		return *this;
	}

	void Swap(Sptr& sp) {
		swap(ptr_, sp.ptr_);
		swap(cnt_, sp.cnt_);
	}

};

二、简单测试

#include <iostream>
#include"SmartPtr.h"
using namespace std;

int main()
{
    SmartPtr<char> pc;//默认构造
    SmartPtr<char> pc0 = SmartPtr<char>();//移动构造
    SmartPtr<char> pc1(new char('a'));//初值构造
    SmartPtr<char> pc2(pc1);//拷贝构造
    SmartPtr<char> pc3(new char('b'));
    SmartPtr<char> pc4;
    SmartPtr<char> pc5(new char('c'));
    
    pc5 = pc4;//pc5引用计数为0,析构掉。
    pc1 = pc3;//正常赋值
    pc1 = pc1;//自我赋值
    cout << "pc0.count = " << pc0.UseCount() << " pc0: nullptr" << endl;
    cout << "pc1.count = " << pc1.UseCount() << " pc1: " << *pc1.Get() << endl;
    cout << "pc2.count = " << pc2.UseCount() << " pc2: " << *pc2.Get() << endl;
    cout << "pc3.count = " << pc3.UseCount() << " pc3: " << *pc3.Get() << endl;

    return 0;
}

三、运行结果

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值