实现简单计数指针

今天看了zthread库中的计数指针,于是也参考着在vs2010上写了一个来巩固对计数指针的理解

#pragma once

template<typename TypeInstance, typename TypeCount = int>
class MyCountPtr
{
	//引用计数指针只要以下两个数据成员
	//指向对象
	TypeInstance* t_instance;
	//指向计数器,计数器默认为int类型
	TypeCount* t_count;
	
public:
	MyCountPtr()
		: t_instance(NULL)
		, t_count(NULL)
	{

	}

	//如果传的参数为空指针,调用以下函数构造,std::nullptr_t为空指针类型
#if defined(_NATIVE_NULLPTR_SUPPORTED) \
	&& !defined(_DO_NOT_USE_NULLPTR)
	MyCountPtr(std::nullptr_t)
		: t_instance(NULL)
		, t_count(NULL)
	{
		std::cout<<"constructor parameter is null\n";
	}
#endif

	//计数指针一般在MyCountPtr对象对t_instance对象进行引用,或解除引用时发生变化

	//1、MyCountPtr<TypeInstance, TypeCount>::MyCountPtr(std::nullptr_t)
	//2、MyCountPtr<TypeInstance, TypeCount>::MyCountPtr<Instance>(innstance* ins)
	//该模版构造函数不需要考虑用户传空指针,传空指针会调用函数1
	//如果不定义为模版函数,则与函数1就变为重载函数,当参数传NULL时,编译器就无法确定调用哪个版本
	//使用时一般使Instance与TypeInstance一致,若不一致必须保证两个类型能够相互转化
	template<typename Instance>
	explicit MyCountPtr(Instance* ins)//explicit拒绝隐式转换,否则编译器会在某些时候将TypeInstance*对象转换成MyCountPtr对象,可能这个结果不是我们想要的
		: t_instance(ins)
		, t_count(new TypeCount())
	{
		++(*t_count);
	}

	//拷贝构造
	MyCountPtr(const MyCountPtr& rh)
		: t_instance(rh.t_instance)
		, t_count(rh.t_count)
	{
		if(t_count)
			++(*t_count);
	}

	//=重载
	MyCountPtr& operator=(const MyCountPtr& rh)
	{
		MyCountPtr<TypeInstance, TypeCount> rhCopy(rh);
		rhCopy.swap(*this);
		return *this;
	}

	//重置对象
	void Reset()
	{
		MyCountPtr<TypeInstance, TypeCount> empty;
		empty.swap(*this);
	}

	//析构,引用计数为0时,释放对象
	~MyCountPtr()
	{
		if(t_count && --(*t_count) == 0)
		{
			if(t_instance)
			{
				std::cout<<"delete instance "<<*t_instance<<std::endl;
				delete t_instance;
			}

			delete t_count;
		}
	}

	//操作符类型转化,将自身转化为bool类型
	operator bool()
	{
		return t_instance != NULL;
	}

	//!操作符重载,专用于判断所管理的对象是否为空
	bool operator!()
	{
		return t_instance == NULL;
	}

	//取值运算符重载,取管理的对象指针
	TypeInstance& operator*()
	{
		return *t_instance;
	}
	
	//反引用符重载,使本对象可以间接调用t_instance对象指针访问他的接口
	TypeInstance* operator->()
	{
		return t_instance;
	}


private:
	//调用标准库的swap直接交换指针实现对象的数据交换
	void swap(MyCountPtr& rh)
	{
		std::swap(t_count, rh.t_count);
		std::swap(t_instance, rh.t_instance);
	}
};

 

测试代码

#include <iostream>
#include "MyCountPtr.h"

int main()
{
	MyCountPtr<int> sp1(new int(2));
	{
		MyCountPtr<int> sp(new int(1));
		//赋值前 sp1为2,引用计数为1,sp为1,引用计数为1
		sp1 = sp;
	}//出括号作用域时输出delete instance 2
	{
		MyCountPtr<int> sp2(sp1);
		//此时 sp1和sp2管理的对象值为1,引用计数为2
	}//出括号作用域时sp1管理的对象值为1,引用计数为1
 
	MyCountPtr<int> p(NULL);//调用空指针参数的构造函数,输出constructor parameter is null
 	MyCountPtr<int> p1(new int(3));
 	MyCountPtr<int> p2(new int(4));
	p1.Reset();//函数返回后输出delete instance 3
	return 0;
}//出函数作用域时依次输出delete instance 4,delete nstance 1
 //4后创建,后创建的靠近栈顶,先销毁

 注:开源库的代码一般都很值得程序员研究和学习,简单的几句话可能蕴含着很多技巧,如赋值操作符和Reset函数实现中用了临时变量去和本对象进行数据交换不但巧妙,而且代码优雅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值