智能指针的两种实现(引用计数)

    在微信上看到一篇“C++引用计数及智能指针的简单实现”的好文章点击打开链接,通俗易懂,激起了敲代码的兴趣,于是用两种方式实现了简单的智能指针(辅助类+SmartPtr类 vs SmartPtr类)。关于什么是智能指针以及普通指针所存在的问题以及什么是引用计数,查看该文即可(讲的很好)点击打开链接,本文仅列出两种实现方式的代码,希望对大家有所帮助,若存在问题,欢迎指正,谢谢!


方式一:辅助类+SmartPtr类(实现原理如下图)



#pragma once

#include<iostream>
using namespace std;

//使用辅助类
template<class T>
class SmartPtr;

/*
	辅助类包含:
		1、引用计数器_count;
		2、指向实际空间的指针_ptr;
*/
template<class T>
class Asistant
{
	friend class SmartPtr<T>;
private:
	Asistant(T *ptr) :_count(1), _ptr(ptr)
	{}
	~Asistant(){
		delete _ptr;
		_ptr = NULL;
	}
	int _count;
	T *_ptr;
};

/*
	智能指针类:(包含)
		1、指向辅助类的指针
*/
template<class T>
class SmartPtr{
public:
	SmartPtr(T *ptr) :_p(new Asistant<T>(ptr))
	{}
	SmartPtr(const SmartPtr<T> &sp){
		_p = sp._p;
		_p->_count++;
	}
	SmartPtr& operator=(const SmartPtr<T> &sp){
		if (this != &sp){
			//处理好原来的关系---->注意:处理好与“前妻”的关系
			if (--(_p->_count) == 0){
				delete _p;         //会先调用辅助类的析构函数(释放实际空间),再释放辅助类对象空间
			}
			//指向新的辅助空间
			_p = sp._p;
			(_p->_count)++;
		}
		return *this;
	}
	~SmartPtr(){
		if (--(_p->_count) == 0){
			delete _p;
			_p = NULL;
		}
	}
	T* operator->(){
		return _p->_ptr;
	}
	T& operator*(){
		return *(_p->_ptr);
	}

private:
	Asistant<T> *_p;
};


方式二:只用一个类中实现Smart_ptr(实现原理如下图)


#pragma once
#include<iostream>
using namespace std;

//在一个类中实现智能指针
template<class T>
class SmartPtr1{
public:
	SmartPtr1(T *ptr) :_countPtr(new int(1)), _ptr(ptr)
	{}
	~SmartPtr1(){
		if (--(*_countPtr) == 0){
			delete _ptr;
			delete _countPtr;
			_ptr = NULL;
			_countPtr = NULL;
		}
	}
	SmartPtr1(const SmartPtr1<T> &sp){
		_countPtr = sp._countPtr;
		++(*_countPtr);
		_ptr = sp._ptr;
	}
	/*
		operator=四部曲:
			1、检查自赋值
			2、与以前“一刀两断”
			3、指向新世界
			4、return *this
	*/
	SmartPtr1& operator=(const SmartPtr1<T> &sp){
		if (this != &sp){
			if (--(*_countPtr) == 0){
				delete _countPtr;
				delete _ptr;
				_countPtr = NULL;
				_ptr = NULL;
			}
			_countPtr = sp._countPtr;
			++(*_countPtr);
			_ptr = sp._ptr;
		}
		return *this;
	}
	T* operator->(){
		return _ptr;
	}
	T& operator*(){
		return *_ptr;
	}
private:
	int *_countPtr;//指向引用计数的指针
	T *_ptr;       //指向实际空间的指针
};

测试程序

#include"SmartPtr.h"
#include"SmartPtr1.h"
#include<vld.h>      //用于检测内存泄露

//垂悬指针:指向已被释放空间的指针
void HangPtr()
{
	int *ptr1 = new int(10);
	int *ptr2 = ptr1;
	int *ptr3 = ptr1;

	cout << "before delete:" << endl;
	cout << *ptr1 << endl;
	cout << *ptr2 << endl;
	cout << *ptr3 << endl;

	cout << "after delete:" << endl;
	delete ptr1;
	cout << *ptr2 << endl;//所指向的空间已被释放--->悬垂指针,程序崩溃“指日可待”
	cout << *ptr3 << endl;
}

//SmartPtr
//-------------------> SmartPtr <---------------------------
//测试拷贝构造函数
void test1(){
	int *p = new int(10);
	SmartPtr<int> sp(p);
	{
		SmartPtr<int> sp1(sp);
	}
	SmartPtr<int> sp2(sp);
}

//测试operator=
void test2()
{
	int *p = new int(10);
	SmartPtr<int> ptr(p);

	int *p1 = new int(20);
	SmartPtr<int> ptr1(p1);

	ptr1 = ptr;
	cout << *ptr << endl;
	cout << *ptr1 << endl;
}

//-------------------> SmartPtr1 <---------------------------
//测试拷贝构造函数
void test3(){
	int *p = new int(10);

	SmartPtr1<int> sp(p);
	{
		SmartPtr1<int> sp1(sp);
	}
	SmartPtr1<int> sp2(sp);
}

//测试operator=
void test4()
{
	int *p = new int(10);
	SmartPtr<int> ptr(p);

	int *p1 = new int(20);
	SmartPtr<int> ptr1(p1);

	ptr1 = ptr;
	cout << *ptr << endl;
	cout << *ptr1 << endl;
}
int main()
{
	test4();
	system("pause");
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值